WeixiangYan/CodeTransOcean huggingface dataset:
Task: 24 game







Python: 

from __future__ import division, print_function
import random, ast, re
import sys

if sys.version_info[0] < 3: input = raw_input

def choose4():
    'four random digits >0 as characters'
    return [str(random.randint(1,9)) for i in range(4)]

def welcome(digits):
    print (__doc__)
    print ("Your four digits: " + ' '.join(digits))

def check(answer, digits):
    allowed = set('() +-*/\t'+''.join(digits))
    ok = all(ch in allowed for ch in answer) and \
         all(digits.count(dig) == answer.count(dig) for dig in set(digits)) \
         and not re.search('\d\d', answer)
    if ok:
        try:
            ast.parse(answer)
        except:
            ok = False
    return ok

def main():    
    digits = choose4()
    welcome(digits)
    trial = 0
    answer = ''
    chk = ans = False
    while not (chk and ans == 24):
        trial +=1
        answer = input("Expression %i: " % trial)
        chk = check(answer, digits)
        if answer.lower() == 'q':
            break
        if answer == '!':
            digits = choose4()
            print ("New digits:", ' '.join(digits))
            continue
        if not chk:
            print ("The input '%s' was wonky!" % answer)
        else:
            ans = eval(answer)
            print (" = ", ans)
            if ans == 24:
                print ("Thats right!")
    print ("Thank you and goodbye")   

if __name__ == '__main__': main()
Task: Enforced immutability







Python: >>> s = "Hello"
>>> s[0] = "h"

Traceback (most recent call last):
  File "<pyshell
    s[0] = "h"
TypeError: 'str' object does not support item assignment
Task: Strange numbers







Python: 



def isStrange(n):
    
    def test(a, b):
        return abs(a - b) in [2, 3, 5, 7]

    xs = digits(n)
    return all(map(test, xs, xs[1:]))




def main():
    

    xs = [
        n for n in range(100, 1 + 500)
        if isStrange(n)
    ]
    print('\nStrange numbers in range [100..500]\n')
    print('(Total: ' + str(len(xs)) + ')\n')
    print(
        '\n'.join(
            ' '.join(
                str(x) for x in row
            ) for row in chunksOf(10)(xs)
        )
    )





def chunksOf(n):
    
    def go(xs):
        return (
            xs[i:n + i] for i in range(0, len(xs), n)
        ) if 0 < n else None
    return go



def digits(n):
    
    return [int(c) for c in str(n)]



if __name__ == '__main__':
    main()
Task: Hofstadter Q sequence







Python: def q(n):
    if n < 1 or type(n) != int: raise ValueError("n must be an int >= 1")
    try:
        return q.seq[n]
    except IndexError:
        ans = q(n - q(n - 1)) + q(n - q(n - 2))
        q.seq.append(ans)
        return ans
q.seq = [None, 1, 1]

if __name__ == '__main__':
    first10 = [q(i) for i in range(1,11)]
    assert first10 == [1, 1, 2, 3, 3, 4, 5, 5, 6, 6], "Q() value error(s)"
    print("Q(n) for n = [1..10] is:", ', '.join(str(i) for i in first10))
    assert q(1000) == 502, "Q(1000) value error"
    print("Q(1000) =", q(1000))
Task: Count occurrences of a substring







Python: >>> "the three truths".count("th")
3
>>> "ababababab".count("abab")
2
Task: Find square difference







Python: import math
print("working...")
limit1 = 6000
limit2 = 1000
oldSquare = 0
newSquare = 0

for n in range(limit1):
    newSquare = n*n
    if (newSquare - oldSquare > limit2):
     print("Least number is = ", end = "");
     print(int(math.sqrt(newSquare)))
     break
    oldSquare = n*n

print("done...")
print()
Task: Rock-paper-scissors







Python: from random import choice

rules = {'rock': 'paper', 'scissors': 'rock', 'paper': 'scissors'}
previous = ['rock', 'paper', 'scissors']

while True:
    human = input('\nchoose your weapon: ')
    computer = rules[choice(previous)]  

    if human in ('quit', 'exit'): break

    elif human in rules:
        previous.append(human)
        print('the computer played', computer, end='; ')

        if rules[computer] == human:  
            print('yay you win!')
        elif rules[human] == computer:  
            print('the computer beat you... :(')
        else: print("it's a tie!")

    else: print("that's not a valid choice")
Task: Benford's law







Python: from __future__ import division
from itertools import islice, count
from collections import Counter
from math import log10
from random import randint

expected = [log10(1+1/d) for d in range(1,10)]

def fib():
    a,b = 1,1
    while True:
        yield a
        a,b = b,a+b


def power_of_threes():
    return (3**k for k in count(0))

def heads(s):
    for a in s: yield int(str(a)[0])

def show_dist(title, s):
    c = Counter(s)
    size = sum(c.values())
    res = [c[d]/size for d in range(1,10)]

    print("\n%s Benfords deviation" % title)
    for r, e in zip(res, expected):
        print("%5.1f%% %5.1f%%  %5.1f%%" % (r*100., e*100., abs(r - e)*100.))

def rand1000():
    while True: yield randint(1,9999)

if __name__ == '__main__':
    show_dist("fibbed", islice(heads(fib()), 1000))
    show_dist("threes", islice(heads(power_of_threes()), 1000))

    
    show_dist("random", islice(heads(rand1000()), 10000))
Task: Hickerson series of almost integers







Python: from decimal import Decimal
import math

def h(n):
    'Simple, reduced precision calculation'
    return math.factorial(n) / (2 * math.log(2) ** (n + 1))
    
def h2(n):
    'Extended precision Hickerson function'
    return Decimal(math.factorial(n)) / (2 * Decimal(2).ln() ** (n + 1))

for n in range(18):
    x = h2(n)
    norm = str(x.normalize())
    almostinteger = (' Nearly integer' 
                     if 'E' not in norm and ('.0' in norm or '.9' in norm) 
                     else ' NOT nearly integer!')
    print('n:%2i h:%s%s' % (n, norm, almostinteger))
Task: Additive primes







Python: def is_prime(n: int) -> bool:
    if n <= 3:
        return n > 1
    if n % 2 == 0 or n % 3 == 0:
        return False
    i = 5
    while i ** 2 <= n:
        if n % i == 0 or n % (i + 2) == 0:
            return False
        i += 6
    return True

def digit_sum(n: int) -> int:
    sum = 0
    while n > 0:
        sum += n % 10
        n //= 10
    return sum

def main() -> None:
    additive_primes = 0
    for i in range(2, 500):
        if is_prime(i) and is_prime(digit_sum(i)):
            additive_primes += 1
            print(i, end=" ")
    print(f"\nFound {additive_primes} additive primes less than 500")

if __name__ == "__main__":
    main()
Task: Extra primes







Python: from itertools import *
from functools import reduce

class Sieve(object):
    
    def __init__(self):
        self._primes = []
        self._comps = {}
        self._max = 2;
    
    def isprime(self, n):
        
        if n >= self._max: self._genprimes(n)
        return n >= 2 and n in self._primes
    
    def _genprimes(self, max):
        while self._max <= max:
            if self._max not in self._comps:
                self._primes.append(self._max)
                self._comps[self._max*self._max] = [self._max]
            else:
                for p in self._comps[self._max]:
                    ps = self._comps.setdefault(self._max+p, [])
                    ps.append(p)
                del self._comps[self._max]
            self._max += 1
                
def extra_primes():
    
    d = [2,3,5,7]
    s = Sieve()
    for cand in chain.from_iterable(product(d, repeat=r) for r in count(1)):
        num = reduce(lambda x, y: x*10+y, cand)
        if s.isprime(num) and s.isprime(sum(cand)): yield num
        
for n in takewhile(lambda n: n < 10000, extra_primes()):
    print(n)
Task: Find prime n such that reversed n is also prime







Python: 

def isPrime(n):
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            return False        
    return True

def isBackPrime(n):
    if not isPrime(n):
        return False
    m = 0
    while n:
        m *= 10
        m += n % 10
        n //= 10
    return isPrime(m)

if __name__ == '__main__':
    for n in range(2, 499):
        if isBackPrime(n):
            print(n, end=' ');
Task: Memory layout of a data structure







Python: from ctypes import Structure, c_int

rs232_9pin  = "_0 CD RD TD DTR SG DSR RTS CTS RI".split()
rs232_25pin = ( "_0  PG  TD  RD  RTS CTS DSR SG  CD  pos neg"
                "_11 SCD SCS STD TC  SRD RC"
                "_18 SRS DTR SQD RI DRS XTC" ).split()

class RS232_9pin(Structure):
    _fields_ = [(__, c_int, 1) for __ in rs232_9pin]

	
class RS232_25pin(Structure):
    _fields_ = [(__, c_int, 1) for __ in rs232_25pin]
Task: Largest proper divisor of n







Python: def lpd(n):
    for i in range(n-1,0,-1):
        if n%i==0: return i
    return 1

for i in range(1,101):
    print("{:3}".format(lpd(i)), end=i%10==0 and '\n' or '')
Task: Numbers with equal rises and falls







Python: import itertools

def riseEqFall(num):
    
    height = 0
    d1 = num % 10
    num //= 10
    while num:
        d2 = num % 10
        height += (d1<d2) - (d1>d2)
        d1 = d2
        num //= 10
    return height == 0
    
def sequence(start, fn):
    
    num=start-1
    while True:
        num += 1
        while not fn(num): num += 1
        yield num

a296712 = sequence(1, riseEqFall)


print("The first 200 numbers are:")
print(*itertools.islice(a296712, 200))


print("The 10,000,000th number is:")
print(*itertools.islice(a296712, 10000000-200-1, 10000000-200))
Task: Pseudo-random numbers_Combined recursive generator MRG32k3a







Python: 
a1 = [0, 1403580, -810728]
m1 = 2**32 - 209

a2 = [527612, 0, -1370589]
m2 = 2**32 - 22853

d = m1 + 1

class MRG32k3a():
    
    def __init__(self, seed_state=123):
        self.seed(seed_state)
    
    def seed(self, seed_state):
        assert 0 <seed_state < d, f"Out of Range 0 x < {d}"
        self.x1 = [seed_state, 0, 0]
        self.x2 = [seed_state, 0, 0]
        
    def next_int(self):
        "return random int in range 0..d"
        x1i = sum(aa * xx  for aa, xx in zip(a1, self.x1)) % m1
        x2i = sum(aa * xx  for aa, xx in zip(a2, self.x2)) % m2
        self.x1 = [x1i] + self.x1[:2]
        self.x2 = [x2i] + self.x2[:2]

        z = (x1i - x2i) % m1
        answer = (z + 1)
        
        return answer
    
    def  next_float(self):
        "return random float between 0 and 1"
        return self.next_int() / d
    

if __name__ == '__main__':
    random_gen = MRG32k3a()
    random_gen.seed(1234567)
    for i in range(5):
        print(random_gen.next_int())
        
    random_gen.seed(987654321)
    hist = {i:0 for i in range(5)}
    for i in range(100_000):
        hist[int(random_gen.next_float() *5)] += 1
    print(hist)
Task: Find words which contains more than 3 e vowels







Python: with open('unixdict.txt', 'rt') as f:
    for line in f.readlines():
        if not any(c in 'aiou' for c in line) and sum(c=='e' for c in line)>3:
            print(line.strip())
Task: Find words with alternating vowels and consonants







Python: 



def isLongAlternator(s):
    
    def p(a, b):
        return isVowel(a) != isVowel(b)
    return 9 < len(s) and all(map(p, s, s[1:]))


def isVowel(c):
    
    return c in 'aeiou'




def main():
    
    matches = [
        x for x in readFile('unixdict.txt').splitlines()
        if isLongAlternator(x)
    ]
    w = max(len(x) for x in matches)
    print(str(len(matches)) + ' matching words:\n')
    print(
        '\n'.join(
            ' '.join(s) for s in chunksOf(4)([
                x.ljust(w, ' ') for x in matches
            ])
        )
    )





def chunksOf(n):
    
    def go(xs):
        return (
            xs[i:n + i] for i in range(0, len(xs), n)
        ) if 0 < n else None
    return go



def readFile(fp):
    
    with open(fp, 'r', encoding='utf-8') as f:
        return f.read()



if __name__ == '__main__':
    main()
Task: Numbers divisible by their individual digits, but not by the product of their digits.







Python: 

from functools import reduce
from operator import mul



def p(n):
    
    digits = [int(c) for c in str(n)]
    return not 0 in digits and (
        0 != (n % reduce(mul, digits, 1))
    ) and all(0 == n % d for d in digits)




def main():
    
    xs = [
        str(n) for n in range(1, 1000)
        if p(n)
    ]
    w = len(xs[-1])
    print(f'{len(xs)} matching numbers:\n')
    print('\n'.join(
        ' '.join(cell.rjust(w, ' ') for cell in row)
        for row in chunksOf(10)(xs)
    ))





def chunksOf(n):
    
    def go(xs):
        return (
            xs[i:n + i] for i in range(0, len(xs), n)
        ) if 0 < n else None
    return go



if __name__ == '__main__':
    main()
Task: Perceptron







Python: import random

TRAINING_LENGTH = 2000

class Perceptron:
    
    def __init__(self,n):
        self.c = .01
        self.weights = [random.uniform(-1.0, 1.0) for _ in range(n)]

    def feed_forward(self, inputs):
        weighted_inputs = []
        for i in range(len(inputs)):
            weighted_inputs.append(inputs[i] * self.weights[i])
        return self.activate(sum(weighted_inputs))

    def activate(self, value):
        return 1 if value > 0 else -1

    def train(self, inputs, desired):
        guess = self.feed_forward(inputs)
        error = desired - guess
        for i in range(len(inputs)):
            self.weights[i] += self.c * error * inputs[i]
        
class Trainer():
    
    def __init__(self, x, y, a):
        self.inputs = [x, y, 1]
        self.answer = a

def F(x):
    return 2 * x + 1

if __name__ == "__main__":
    ptron = Perceptron(3)
    training = []
    for i in range(TRAINING_LENGTH):
        x = random.uniform(-10,10)
        y = random.uniform(-10,10)
        answer = 1
        if y < F(x): answer = -1
        training.append(Trainer(x,y,answer))
    result = []
    for y in range(-10,10):
        temp = []
        for x in range(-10,10):
            if ptron.feed_forward([x,y,1]) == 1:
                temp.append('^')
            else:
                temp.append('.')
        result.append(temp)
    
    print('Untrained')
    for row in result:
        print(''.join(v for v in row))

    for t in training:
        ptron.train(t.inputs, t.answer)
    
    result = []
    for y in range(-10,10):
        temp = []
        for x in range(-10,10):
            if ptron.feed_forward([x,y,1]) == 1:
                temp.append('^')
            else:
                temp.append('.')
        result.append(temp)
    
    print('Trained')
    for row in result:
        print(''.join(v for v in row))
Task: Video display modes

C: #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "wren.h"

void C_xrandr(WrenVM* vm) {
     const char *arg = wrenGetSlotString(vm, 1);
     char command[strlen(arg) + 8];
     strcpy(command, "xrandr ");
     strcat(command, arg);
     system(command);
}

void C_usleep(WrenVM* vm) {
    useconds_t usec = (useconds_t)wrenGetSlotDouble(vm, 1);
    usleep(usec);
}

WrenForeignMethodFn bindForeignMethod(
    WrenVM* vm,
    const char* module,
    const char* className,
    bool isStatic,
    const char* signature) {
    if (strcmp(module, "main") == 0) {
        if (strcmp(className, "C") == 0) {
            if (isStatic && strcmp(signature, "xrandr(_)") == 0) return C_xrandr;
            if (isStatic && strcmp(signature, "usleep(_)") == 0) return C_usleep;
        }
    }
    return NULL;
}

static void writeFn(WrenVM* vm, const char* text) {
    printf("%s", text);
}

char *readFile(const char *fileName) {
    FILE *f = fopen(fileName, "r");
    fseek(f, 0, SEEK_END);
    long fsize = ftell(f);
    rewind(f);
    char *script = malloc(fsize + 1);
    fread(script, 1, fsize, f);
    fclose(f);
    script[fsize] = 0;
    return script;
}

int main(int argc, char **argv) {
    WrenConfiguration config;
    wrenInitConfiguration(&config);
    config.writeFn = &writeFn;
    config.bindForeignMethodFn = &bindForeignMethod;
    WrenVM* vm = wrenNewVM(&config);
    const char* module = "main";
    const char* fileName = "video_display_modes.wren";
    char *script = readFile(fileName);
    wrenInterpret(vm, module, script);
    wrenFreeVM(vm);
    free(script);
    return 0;
}
Task: XML validation

C: #include <libxml/xmlschemastypes.h>

int main(int argC, char** argV)
{
	if (argC <= 2) {
		printf("Usage: %s <XML Document Name> <XSD Document Name>\n", argV[0]);
		return 0;
	}
	
	xmlDocPtr doc;
	xmlSchemaPtr schema = NULL;
	xmlSchemaParserCtxtPtr ctxt;
	char *XMLFileName = argV[1];
	char *XSDFileName = argV[2];
	int ret;

	xmlLineNumbersDefault(1);

	ctxt = xmlSchemaNewParserCtxt(XSDFileName);

	xmlSchemaSetParserErrors(ctxt, (xmlSchemaValidityErrorFunc) fprintf, (xmlSchemaValidityWarningFunc) fprintf, stderr);
	schema = xmlSchemaParse(ctxt);
	xmlSchemaFreeParserCtxt(ctxt);


	doc = xmlReadFile(XMLFileName, NULL, 0);

	if (doc == NULL){
		fprintf(stderr, "Could not parse %s\n", XMLFileName);
	}
	else{
		xmlSchemaValidCtxtPtr ctxt;

		ctxt = xmlSchemaNewValidCtxt(schema);
		xmlSchemaSetValidErrors(ctxt, (xmlSchemaValidityErrorFunc) fprintf, (xmlSchemaValidityWarningFunc) fprintf, stderr);
		ret = xmlSchemaValidateDoc(ctxt, doc);
		
		if (ret == 0){
			printf("%s validates\n", XMLFileName);
		}
		else if (ret > 0){
			printf("%s fails to validate\n", XMLFileName);
		}
		else{
			printf("%s validation generated an internal error\n", XMLFileName);
		}
		xmlSchemaFreeValidCtxt(ctxt);
		xmlFreeDoc(doc);
	}


	if(schema != NULL)
		xmlSchemaFree(schema);

	xmlSchemaCleanupTypes();
	xmlCleanupParser();
	xmlMemoryDump();

	return 0;
}
Task: Singly-linked list_Element removal

C: #include<stdlib.h>
#include<stdio.h>

typedef struct elem{
	int data;
	struct elem* next;
}cell;

typedef cell* list;

list addToList(list a,int num){
	
	list iter, temp;
	int i=0;
	
	if(a==NULL){
		a = (list)malloc(sizeof(cell));
		a->data = num;
		a->next = NULL;
	}
	else{
		iter = a;
		
		while(iter->next!=NULL){
			iter = iter->next;
		}
		
		temp = (list)malloc(sizeof(cell));
		temp->data = num;
		temp->next = NULL;
		
		iter->next = temp;
	}	
	return a;
}

list deleteFromList(list a,int pos){
	
	int i=1;
	list temp,iter;
	
	if(a!=NULL){
		iter = a;
		
		if(pos==1){
			a = a->next;
			iter->next = NULL;
			free(iter);
		}
		
		else{
			while(i++!=pos-1)
				iter = iter->next;
			temp = iter->next;
			iter->next = temp->next;
			temp->next = NULL;
			free(temp);
		}
	}
	return a;
}

void printList(list a){
	list temp = a;
	
	printf("List contains following elements : \n");
	
	while(temp!=NULL){
		printf("%d ",temp->data);
		temp = temp->next;
	}
}

int main(int argC,char* argV[])
{
	list a = NULL;
	int i;
	
	if(argC == 1)
		printf("Usage : %s <list of integers to be inserted into the list>",argV[0]);
	else{
		for(i=2;i<=argC;i++)
			a = addToList(a,atoi(argV[i-1]));
		
		printList(a);
		
		do{
			printf("\nEnter position of element to be removed (1-%d) : ",argC-1);
			
			scanf("%d",&i);
			
			if(i>0 && i<=argC-1){
				a = deleteFromList(a,i);
				printList(a);
			}
		}while(i>argC-1||i<=0);
	}
	return 0;
}
Task: Special factorials

C: #include <math.h>
#include <stdint.h>
#include <stdio.h>


uint64_t factorial(int n) {
    uint64_t result = 1;
    int i;

    for (i = 1; i <= n; i++) {
        result *= i;
    }

    return result;
}


int inverse_factorial(uint64_t f) {
    int p = 1;
    int i = 1;

    if (f == 1) {
        return 0;
    }

    while (p < f) {
        p *= i;
        i++;
    }

    if (p == f) {
        return i - 1;
    }
    return -1;
}


uint64_t super_factorial(int n) {
    uint64_t result = 1;
    int i;

    for (i = 1; i <= n; i++) {
        result *= factorial(i);
    }

    return result;
}


uint64_t hyper_factorial(int n) {
    uint64_t result = 1;
    int i;

    for (i = 1; i <= n; i++) {
        result *= (uint64_t)powl(i, i);
    }

    return result;
}


uint64_t alternating_factorial(int n) {
    uint64_t result = 0;
    int i;

    for (i = 1; i <= n; i++) {
        if ((n - i) % 2 == 0) {
            result += factorial(i);
        } else {
            result -= factorial(i);
        }
    }

    return result;
}


uint64_t exponential_factorial(int n) {
    uint64_t result = 0;
    int i;

    for (i = 1; i <= n; i++) {
        result = (uint64_t)powl(i, (long double)result);
    }

    return result;
}

void test_factorial(int count, uint64_t(*func)(int), char *name) {
    int i;

    printf("First %d %s:\n", count, name);
    for (i = 0; i < count ; i++) {
        printf("%llu ", func(i));
    }
    printf("\n");
}

void test_inverse(uint64_t f) {
    int n = inverse_factorial(f);
    if (n < 0) {
        printf("rf(%llu) = No Solution\n", f);
    } else {
        printf("rf(%llu) = %d\n", f, n);
    }
}

int main() {
    int i;

    
    test_factorial(9, super_factorial, "super factorials");
    printf("\n");

    
    test_factorial(8, super_factorial, "hyper factorials");
    printf("\n");

    test_factorial(10, alternating_factorial, "alternating factorials");
    printf("\n");

    test_factorial(5, exponential_factorial, "exponential factorials");
    printf("\n");

    test_inverse(1);
    test_inverse(2);
    test_inverse(6);
    test_inverse(24);
    test_inverse(120);
    test_inverse(720);
    test_inverse(5040);
    test_inverse(40320);
    test_inverse(362880);
    test_inverse(3628800);
    test_inverse(119);

    return 0;
}
Task: Tarjan

C: #include <stddef.h>
#include <stdlib.h>
#include <stdbool.h>

#ifndef min
#define min(x, y) ((x)<(y) ? (x) : (y))
#endif

struct edge {
	void *from;
	void *to;
};

struct components {
	int nnodes;
	void **nodes;
	struct components *next;
};

struct node {
	int index;
	int lowlink;
	bool onStack;
	void *data;
};

struct tjstate {
	int index;
	int sp;
	int nedges;
	struct edge *edges;
	struct node **stack;
	struct components *head;
	struct components *tail;
};

static int nodecmp(const void *l, const void *r)
{
	return (ptrdiff_t)l -(ptrdiff_t)((struct node *)r)->data;
}

static int strongconnect(struct node *v, struct tjstate *tj)
{
	struct node *w;

	
	v->index = tj->index;
	v->lowlink = tj->index;
	tj->index++;
	tj->stack[tj->sp] = v;
	tj->sp++;
	v->onStack = true;

	for (int i = 0; i<tj->nedges; i++) {
		
		if (tj->edges[i].from != v) {
			continue;
		}
		w = tj->edges[i].to;
		
		if (w->index == -1) {
			int r = strongconnect(w, tj);
			if (r != 0)
				return r;
			v->lowlink = min(v->lowlink, w->lowlink);
		
		} else if (w->onStack) {
			v->lowlink = min(v->lowlink, w->index);
		}
	}

	
	if (v->lowlink == v->index) {
		struct components *ng = malloc(sizeof(struct components));
		if (ng == NULL) {
			return 2;
		}
		if (tj->tail == NULL) {
			tj->head = ng;
		} else {
			tj->tail->next = ng;
		}
		tj->tail = ng;
		ng->next = NULL;
		ng->nnodes = 0;
		do {
			tj->sp--;
			w = tj->stack[tj->sp];
			w->onStack = false;
			ng->nnodes++;
		} while (w != v);
		ng->nodes = malloc(ng->nnodes*sizeof(void *));
		if (ng == NULL) {
			return 2;
		}
		for (int i = 0; i<ng->nnodes; i++) {
			ng->nodes[i] = tj->stack[tj->sp+i]->data;
		}
	}
	return 0;
}

static int ptrcmp(const void *l, const void *r)
{
	return (ptrdiff_t)((struct node *)l)->data
		- (ptrdiff_t)((struct node *)r)->data;
}


struct components *tarjans(
		int nnodes, void *nodedata[],
		int nedges, struct edge *edgedata[],
		int *error)
{
	struct node nodes[nnodes];
	struct edge edges[nedges];
	struct node *stack[nnodes];
	struct node *from, *to;
	struct tjstate tj = {0, 0, nedges, edges, stack, NULL, .tail=NULL};

	
	for (int i = 0; i<nnodes; i++) {
		nodes[i] = (struct node){-1, -1, false, nodedata[i]};
	}
	qsort(nodes, nnodes, sizeof(struct node), ptrcmp);

	
	for (int i = 0; i<nedges; i++) {
		from = bsearch(edgedata[i]->from, nodes, nnodes,
			sizeof(struct node), nodecmp);
		if (from == NULL) {
			*error = 1;
			return NULL;
		}
		to = bsearch(edgedata[i]->to, nodes, nnodes,
			sizeof(struct node), nodecmp);
		if (to == NULL) {
			*error = 1;
			return NULL;
		}
		edges[i] = (struct edge){.from=from, .to=to};
	}

	
	for (int i = 0; i < nnodes; i++) {
		if (nodes[i].index == -1) {
			*error = strongconnect(&nodes[i], &tj);
			if (*error != 0)
				return NULL;
		}
	}
	return tj.head;
}