/* ARM assembly Raspberry PI  */
/*  program noconnpuzzle.s   */

/************************************/
/* Constantes                       */
/************************************/
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall

.equ NBBOX,  8
.equ POSA,   5

/*********************************/
/* Initialized data              */
/*********************************/
.data
sMessDeb:           .ascii "a="
sMessValeur_a:     .fill 11, 1, ' '            @ size => 11
                    .ascii "b="
sMessValeur_b:     .fill 11, 1, ' '            @ size => 11
                    .ascii "c="
sMessValeur_c:     .fill 11, 1, ' '            @ size => 11
                    .ascii "d="
sMessValeur_d:     .fill 11, 1, ' '            @ size => 11
                    .ascii "\n"
                    .ascii "e="
sMessValeur_e:     .fill 11, 1, ' '            @ size => 11
                    .ascii "f="
sMessValeur_f:     .fill 11, 1, ' '            @ size => 11
                    .ascii "g="
sMessValeur_g:     .fill 11, 1, ' '            @ size => 11
                    .ascii "h="
sMessValeur_h:     .fill 11, 1, ' '            @ size => 11

szCarriageReturn:   .asciz "\n************************\n"

szMessLine1:            .asciz "               \n"
szMessLine2:            .asciz "    /|\\ /|\\  \n"
szMessLine3:            .asciz "   / | X | \\     \n"
szMessLine4:            .asciz "  /  |/ \\|  \\     \n"
szMessLine5:            .asciz "   -   - | -     \n"
szMessLine6:            .asciz "  \\  |\\ /|  /  \n"
szMessLine7:            .asciz "   \\ | X | /  \n"
szMessLine8:            .asciz "    \\|/ \\|/   \n"
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
iValues_a:                .skip 4 * NBBOX
iValues_b:                .skip 4 * NBBOX - 1
iValues_c:                .skip 4 * NBBOX - 2
iValues_d:                .skip 4 * NBBOX - 3
iValues_e:                .skip 4 * NBBOX - 4
iValues_f:                .skip 4 * NBBOX - 5
iValues_g:                .skip 4 * NBBOX - 6
iValues_h:                .skip 4 * NBBOX - 7
sConvValue:               .skip 12
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                             @ entry of program
    mov r0,#1
    mov r1,#8
    bl searchPb

100:                                              @ standard end of the program
    mov r0, #0                                    @ return code
    mov r7, #EXIT                                 @ request to exit program
    svc #0                                        @ perform the system call

iAdrszCarriageReturn:            .int szCarriageReturn

/******************************************************************/
/*     search problem  unique solution                            */
/******************************************************************/
/* r0 contains start digit */
/* r1 contains end digit */
searchPb:
    push {r0-r12,lr}                                  @ save  registers
    @ init
    ldr r3,iAdriValues_a                              @ area value a
    mov r4,#0
1:                                                    @ loop init value a
    str r0,[r3,r4,lsl #2]
    add r4,#1
    add r0,#1
    cmp r0,r1
    ble 1b

    mov r12,#-1
2:
    add r12,#1                                        @ increment indice a
    cmp r12,#NBBOX-1
    bgt 90f
    ldr r0,iAdriValues_a                              @ area value a
    ldr r1,iAdriValues_b                              @ area value b
    mov r2,r12                                        @ indice  a
    mov r3,#NBBOX                                     @ number of origin values
    bl prepValues
    mov r11,#-1
3:
    add r11,#1                                        @ increment indice b
    cmp r11,#NBBOX - 2
    bgt 2b
    ldr r0,iAdriValues_b                              @ area value b
    ldr r1,iAdriValues_c                              @ area value c
    mov r2,r11                                        @ indice b
    mov r3,#NBBOX -1                                  @ number of origin values
    bl prepValues
    mov r10,#-1
4:
    add r10,#1
    cmp r10,#NBBOX - 3
    bgt 3b
    ldr r0,iAdriValues_a
    ldr r0,[r0,r12,lsl #2]
    ldr r1,iAdriValues_c
    ldr r1,[r1,r10,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 4b
    ldr r0,iAdriValues_c
    ldr r1,iAdriValues_d
    mov r2,r10
    mov r3,#NBBOX - 2
    bl prepValues
    mov r9,#-1
5:
    add r9,#1
    cmp r9,#NBBOX - 4
    bgt 4b
    @ control d   / a b c
    ldr r0,iAdriValues_d
    ldr r0,[r0,r9,lsl #2]
    ldr r1,iAdriValues_a
    ldr r1,[r1,r12,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 5b
    ldr r1,iAdriValues_b
    ldr r1,[r1,r11,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 5b
    ldr r1,iAdriValues_c
    ldr r1,[r1,r10,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 5b

    ldr r0,iAdriValues_d
    ldr r1,iAdriValues_e
    mov r2,r9
    mov r3,#NBBOX - 3
    bl prepValues
    mov r8,#-1
6:
    add r8,#1
    cmp r8,#NBBOX - 5
    bgt 5b
    @ control e   / a b d
    ldr r0,iAdriValues_e
    ldr r0,[r0,r8,lsl #2]
    ldr r1,iAdriValues_a
    ldr r1,[r1,r12,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 6b
    ldr r1,iAdriValues_b
    ldr r1,[r1,r11,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 6b
    ldr r1,iAdriValues_d
    ldr r1,[r1,r9,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 6b

    ldr r0,iAdriValues_e
    ldr r1,iAdriValues_f
    mov r2,r8
    mov r3,#NBBOX - 4
    bl prepValues
    mov r7,#-1
7:
    add r7,#1
    cmp r7,#NBBOX - 6
    bgt 6b
    @ control f   / b e
    ldr r0,iAdriValues_f
    ldr r0,[r0,r7,lsl #2]
    ldr r1,iAdriValues_b
    ldr r1,[r1,r11,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 7b
    ldr r1,iAdriValues_e
    ldr r1,[r1,r8,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 7b

    ldr r0,iAdriValues_f
    ldr r1,iAdriValues_g
    mov r2,r7
    mov r3,#NBBOX - 5
    bl prepValues
    mov r6,#-1
8:
    add r6,#1
    cmp r6,#NBBOX - 7
    bgt 7b
    @ control g   / c d e
    ldr r0,iAdriValues_g
    ldr r0,[r0,r6,lsl #2]
    ldr r1,iAdriValues_c
    ldr r1,[r1,r10,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 8b
    ldr r1,iAdriValues_d
    ldr r1,[r1,r9,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 8b
    ldr r1,iAdriValues_e
    ldr r1,[r1,r8,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 8b
    ldr r0,iAdriValues_g
    ldr r1,iAdriValues_h
    mov r2,r6
    mov r3,#NBBOX - 6
    bl prepValues
    mov r5,#-1
9:
    add r5,#1
    cmp r5,#NBBOX - 8
    bgt 8b
    @ control h   / d e f
    ldr r0,iAdriValues_h
    ldr r0,[r0,r5,lsl #2]
    ldr r1,iAdriValues_d
    ldr r1,[r1,r9,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 9b
    ldr r1,iAdriValues_e
    ldr r1,[r1,r8,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 9b
    ldr r1,iAdriValues_f
    ldr r1,[r1,r7,lsl #2]
    subs r2,r1,r0
    mvnlt r2,r2
    addlt r2,#1
    cmp r2,#1
    beq 9b
    @ solution ok   display text
    ldr r0,iAdriValues_a
    ldr r0,[r0,r12,lsl #2]
    ldr r1,iAdrsMessValeur_a
    bl conversion10
    ldr r0,iAdriValues_b
    ldr r0,[r0,r11,lsl #2]
    ldr r1,iAdrsMessValeur_b
    bl conversion10
    ldr r0,iAdriValues_c
    ldr r0,[r0,r10,lsl #2]
    ldr r1,iAdrsMessValeur_c
    bl conversion10
    ldr r0,iAdriValues_d
    ldr r0,[r0,r9,lsl #2]
    ldr r1,iAdrsMessValeur_d
    bl conversion10
    ldr r0,iAdriValues_e
    ldr r0,[r0,r8,lsl #2]
    ldr r1,iAdrsMessValeur_e
    bl conversion10
    ldr r0,iAdriValues_f
    ldr r0,[r0,r7,lsl #2]
    ldr r1,iAdrsMessValeur_f
    bl conversion10
    ldr r0,iAdriValues_g
    ldr r0,[r0,r6,lsl #2]
    ldr r1,iAdrsMessValeur_g
    bl conversion10
    ldr r0,iAdriValues_h
    ldr r0,[r0,r5,lsl #2]
    ldr r1,iAdrsMessValeur_h
    bl conversion10
    ldr r0,iAdrsMessDeb
    bl affichageMess

    @ display design
    ldr r0,iAdriValues_a
    ldr r0,[r0,r12,lsl #2]
    ldr r1,iAdrsConvValue
    bl conversion10
    ldrb r2,[r1]
    ldr r0,iAdrszMessLine1
    strb r2,[r0,#POSA]
    ldr r0,iAdriValues_b
    ldr r0,[r0,r11,lsl #2]
    ldr r1,iAdrsConvValue
    bl conversion10
    ldrb r2,[r1]
    ldr r0,iAdrszMessLine1
    strb r2,[r0,#POSA+4]
    bl affichageMess
    ldr r0,iAdrszMessLine2
    bl affichageMess
    ldr r0,iAdrszMessLine3
    bl affichageMess
    ldr r0,iAdrszMessLine4
    bl affichageMess
    ldr r0,iAdriValues_c
    ldr r0,[r0,r10,lsl #2]
    ldr r1,iAdrsConvValue
    bl conversion10
    ldrb r2,[r1]
    ldr r0,iAdrszMessLine5
    strb r2,[r0,#POSA-4]
    ldr r0,iAdriValues_d
    ldr r0,[r0,r9,lsl #2]
    ldr r1,iAdrsConvValue
    bl conversion10
    ldrb r2,[r1]
    ldr r0,iAdrszMessLine5
    strb r2,[r0,#POSA]
    ldr r0,iAdriValues_e
    ldr r0,[r0,r8,lsl #2]
    ldr r1,iAdrsConvValue
    bl conversion10
    ldrb r2,[r1]
    ldr r0,iAdrszMessLine5
    strb r2,[r0,#POSA+4]
    ldr r0,iAdriValues_f
    ldr r0,[r0,r7,lsl #2]
    ldr r1,iAdrsConvValue
    bl conversion10
    ldrb r2,[r1]
    ldr r0,iAdrszMessLine5
    strb r2,[r0,#POSA+8]
    bl affichageMess
    ldr r0,iAdrszMessLine6
    bl affichageMess
    ldr r0,iAdrszMessLine7
    bl affichageMess
    ldr r0,iAdrszMessLine8
    bl affichageMess
    ldr r0,iAdriValues_g
    ldr r0,[r0,r6,lsl #2]
    ldr r1,iAdrsConvValue
    bl conversion10
    ldrb r2,[r1]
    ldr r0,iAdrszMessLine1
    strb r2,[r0,#POSA]
    ldr r0,iAdriValues_h
    ldr r0,[r0,r5,lsl #2]
    ldr r1,iAdrsConvValue
    bl conversion10
    ldrb r2,[r1]
    ldr r0,iAdrszMessLine1
    strb r2,[r0,#POSA+4]
    bl affichageMess

    //b 9b                   @ loop for other solution
90:

100:
    pop {r0-r12,lr}                               @ restaur registers
    bx lr                                         @return
iAdriValues_a:                   .int iValues_a
iAdriValues_b:                   .int iValues_b
iAdriValues_c:                   .int iValues_c
iAdriValues_d:                   .int iValues_d
iAdriValues_e:                   .int iValues_e
iAdriValues_f:                   .int iValues_f
iAdriValues_g:                   .int iValues_g
iAdriValues_h:                   .int iValues_h

iAdrsMessValeur_a:               .int sMessValeur_a
iAdrsMessValeur_b:               .int sMessValeur_b
iAdrsMessValeur_c:               .int sMessValeur_c
iAdrsMessValeur_d:               .int sMessValeur_d
iAdrsMessValeur_e:               .int sMessValeur_e
iAdrsMessValeur_f:               .int sMessValeur_f
iAdrsMessValeur_g:               .int sMessValeur_g
iAdrsMessValeur_h:               .int sMessValeur_h
iAdrsMessDeb:                    .int sMessDeb

iAdrsConvValue:                  .int sConvValue
iAdrszMessLine1:                 .int szMessLine1
iAdrszMessLine2:                 .int szMessLine2
iAdrszMessLine3:                 .int szMessLine3
iAdrszMessLine4:                 .int szMessLine4
iAdrszMessLine5:                 .int szMessLine5
iAdrszMessLine6:                 .int szMessLine6
iAdrszMessLine7:                 .int szMessLine7
iAdrszMessLine8:                 .int szMessLine8
/******************************************************************/
/*     copy value area  and substract value of indice             */
/******************************************************************/
/* r0 contains the address of values origin */
/* r1 contains the address of values destination */
/* r2 contains value indice to substract     */
/* r3 contains origin values number          */
prepValues:
    push {r1-r6,lr}                                @ save  registres
    mov r4,#0                                      @ indice origin value
    mov r5,#0                                      @ indice destination value
1:
    cmp r4,r2                                      @ substract indice ?
    beq 2f                                         @ yes -> jump
    ldr r6,[r0,r4,lsl #2]                          @ no -> copy value
    str r6,[r1,r5,lsl #2]
    add r5,#1                                      @ increment destination indice
2:
   add r4,#1                                       @ increment origin indice
   cmp r4,r3                                       @ end ?
   blt 1b
100:
    pop {r1-r6,lr}                                 @ restaur registres
    bx lr                                          @return
/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                          @ save  registres
    mov r2,#0                                      @ counter length
1:                                                 @ loop length calculation
    ldrb r1,[r0,r2]                                @ read octet start position + index
    cmp r1,#0                                      @ if 0 its over
    addne r2,r2,#1                                 @ else add 1 in the length
    bne 1b                                         @ and loop
                                                   @ so here r2 contains the length of the message
    mov r1,r0                                      @ address message in r1
    mov r0,#STDOUT                                 @ code to write to the standard output Linux
    mov r7, #WRITE                                 @ code call system "write"
    svc #0                                         @ call systeme
    pop {r0,r1,r2,r7,lr}                           @ restaur des  2 registres */
    bx lr                                          @ return
/******************************************************************/
/*     Converting a register to a decimal unsigned                */
/******************************************************************/
/* r0 contains value and r1 address area   */
/* r0 return size of result (no zero final in area) */
/* area size => 11 bytes          */
.equ LGZONECAL,   10
conversion10:
    push {r1-r4,lr}                                 @ save registers
    mov r3,r1
    mov r2,#LGZONECAL
1:                                                  @ start loop
    bl divisionpar10U                               @ unsigned  r0 <- dividende. quotient ->r0 reste -> r1
    add r1,#48                                      @ digit
    strb r1,[r3,r2]                                 @ store digit on area
    cmp r0,#0                                       @ stop if quotient = 0
    subne r2,#1                                     @ else previous position
    bne 1b                                          @ and loop
                                                    @ and move digit from left of area
    mov r4,#0
2:
    ldrb r1,[r3,r2]
    strb r1,[r3,r4]
    add r2,#1
    add r4,#1
    cmp r2,#LGZONECAL
    ble 2b
                                                      @ and move spaces in end on area
    mov r0,r4                                         @ result length
    mov r1,#' '                                       @ space
3:
    strb r1,[r3,r4]                                   @ store space in area
    add r4,#1                                         @ next position
    cmp r4,#LGZONECAL
    ble 3b                                            @ loop if r4 <= area size

100:
    pop {r1-r4,lr}                                    @ restaur registres
    bx lr                                             @return

/***************************************************/
/*   division par 10   unsigned                    */
/***************************************************/
/* r0 dividende   */
/* r0 quotient    */
/* r1 remainder   */
divisionpar10U:
    push {r2,r3,r4, lr}
    mov r4,r0                                          @ save value
    ldr r3,iMagicNumber                                @ r3 <- magic_number    raspberry 1 2
    umull r1, r2, r3, r0                               @ r1<- Lower32Bits(r1*r0) r2<- Upper32Bits(r1*r0)
    mov r0, r2, LSR #3                                 @ r2 <- r2 >> shift 3
    add r2,r0,r0, lsl #2                               @ r2 <- r0 * 5
    sub r1,r4,r2, lsl #1                               @ r1 <- r4 - (r2 * 2)  = r4 - (r0 * 10)
    pop {r2,r3,r4,lr}
    bx lr                                              @ leave function
iMagicNumber:  	.int 0xCCCCCCCD


oGrid := [[ "", "X", "X"]							; setup oGrid
	,[ "X", "X", "X", "X"]
	,[  "", "X", "X"]]

oNeighbor := [], oCell := [], 	oRoute := [] , oVisited := []			; initialize objects

for row, oRow in oGrid
	for col, val in oRow
		if val								; for each valid cell in oGrid
			oNeighbor[row, col] := Neighbors(row, col, oGrid)	; list valid no-connection neighbors

Solve:
for row, oRow in oGrid
	for col , val in oRow
		if val								; for each valid cell in oGrid
			if (oSolution := SolveNoConnect(row, col, 1)).8		; solve for this cell
				break, Solve					; if solution found stop

; show solution
for i , val in oSolution
	oCell[StrSplit(val, ":").1 , StrSplit(val, ":").2] := i

		  A := oCell[1, 2]	, B := oCell[1, 3]
C := oCell[2, 1], D := oCell[2, 2]	, E := oCell[2, 3], 	F := oCell[2, 4]
		  G := oCell[3, 2]	, H := oCell[3, 3]
sol =
(

    %A%   %B%
   /|\ /|\
  / | X | \
 /  |/ \|  \
%C% - %D% - %E% - %F%
 \  |\ /|  /
  \ | X | /
   \|/ \|/
    %G%   %H%
)
MsgBox % sol
return
;-----------------------------------------------------------------------
SolveNoConnect(row, col, val){
	global
	oRoute.push(row ":" col)						; save route
	oVisited[row, col] := true						; mark this cell visited

	if oRoute[8]								; if solution found
		return true							; end recursion

	for each, nn in StrSplit(oNeighbor[row, col], ",") 			; for each no-connection neighbor of cell
	{
		rowX := StrSplit(nn, ":").1	, colX := StrSplit(nn, ":").2	; get coords of this neighbor
		if !oVisited[rowX, colX]					; if not previously visited
		{
			oVisited[rowX, colX] := true				; mark this cell visited
			val++							; increment
			if (SolveNoConnect(rowX, colX, val))			; recurse
				return oRoute					; if solution found return route
		}
	}
	oRoute.pop()								; Solution not found, backtrack oRoute
	oVisited[row, col] := false						; Solution not found, remove mark
}
;-----------------------------------------------------------------------
Neighbors(row, col, oGrid){							; return distant neighbors of oGrid[row,col]
	for r , oRow in oGrid
		for c, v in oRow
			if (v="X") && (abs(row-r) > 1 || abs(col-c) > 1)
				list .= r ":"c ","
	if (row<>2) && oGrid[row, col]
		list .= oGrid[row, col+1] ? row ":" col+1 "," : oGrid[row, col-1] ? row ":" col-1 "," : ""
	return Trim(list, ",")
}


#include <stdbool.h>
#include <stdio.h>
#include <math.h>

int connections[15][2] = {
    {0, 2}, {0, 3}, {0, 4}, // A to C,D,E
    {1, 3}, {1, 4}, {1, 5}, // B to D,E,F
    {6, 2}, {6, 3}, {6, 4}, // G to C,D,E
    {7, 3}, {7, 4}, {7, 5}, // H to D,E,F
    {2, 3}, {3, 4}, {4, 5}, // C-D, D-E, E-F
};

int pegs[8];
int num = 0;

bool valid() {
    int i;
    for (i = 0; i < 15; i++) {
        if (abs(pegs[connections[i][0]] - pegs[connections[i][1]]) == 1) {
            return false;
        }
    }
    return true;
}

void swap(int *a, int *b) {
    int t = *a;
    *a = *b;
    *b = t;
}

void printSolution() {
    printf("----- %d -----\n", num++);
    printf("  %d %d\n", /*        */ pegs[0], pegs[1]);
    printf("%d %d %d %d\n", pegs[2], pegs[3], pegs[4], pegs[5]);
    printf("  %d %d\n", /*        */ pegs[6], pegs[7]);
    printf("\n");
}

void solution(int le, int ri) {
    if (le == ri) {
        if (valid()) {
            printSolution();
        }
    } else {
        int i;
        for (i = le; i <= ri; i++) {
            swap(pegs + le, pegs + i);
            solution(le + 1, ri);
            swap(pegs + le, pegs + i);
        }
    }
}

int main() {
    int i;
    for (i = 0; i < 8; i++) {
        pegs[i] = i + 1;
    }

    solution(0, 8 - 1);
    return 0;
}


#include <array>
#include <iostream>
#include <vector>

std::vector<std::pair<int, int>> connections = {
    {0, 2}, {0, 3}, {0, 4}, // A to C,D,E
    {1, 3}, {1, 4}, {1, 5}, // B to D,E,F
    {6, 2}, {6, 3}, {6, 4}, // G to C,D,E
    {7, 3}, {7, 4}, {7, 5}, // H to D,E,F
    {2, 3}, {3, 4}, {4, 5}, // C-D, D-E, E-F
};
std::array<int, 8> pegs;
int num = 0;

void printSolution() {
    std::cout << "----- " << num++ << " -----\n";
    std::cout << "  " /*     */ << pegs[0] << ' ' << pegs[1] << '\n';
    std::cout << pegs[2] << ' ' << pegs[3] << ' ' << pegs[4] << ' ' << pegs[5] << '\n';
    std::cout << "  " /*     */ << pegs[6] << ' ' << pegs[7] << '\n';
    std::cout << '\n';
}

bool valid() {
    for (size_t i = 0; i < connections.size(); i++) {
        if (abs(pegs[connections[i].first] - pegs[connections[i].second]) == 1) {
            return false;
        }
    }
    return true;
}

void solution(int le, int ri) {
    if (le == ri) {
        if (valid()) {
            printSolution();
        }
    } else {
        for (size_t i = le; i <= ri; i++) {
            std::swap(pegs[le], pegs[i]);
            solution(le + 1, ri);
            std::swap(pegs[le], pegs[i]);
        }
    }
}

int main() {
    pegs = { 1, 2, 3, 4, 5, 6, 7, 8 };
    solution(0, pegs.size() - 1);
    return 0;
}


type hole = int;
param A : hole = 1;
param B : hole = A+1;
param C : hole = B+1;
param D : hole = C+1;
param E : hole = D+1;
param F : hole = E+1;
param G : hole = F+1;
param H : hole = G+1;
param starting : int = 0;
const holes : domain(hole) = { A,B,C,D,E,F,G,H };
const graph : [holes] domain(hole) = [  A => { C,D,E },
                                        B => { D,E,F },
                                        C => { A,D,G },
                                        D => { A,B,C,E,G,H },
                                        E => { A,B,D,F,G,H },
                                        F => { B,E,H },
                                        G => { C,D,E },
                                        H => { D,E,F }
                                      ];

proc check( configuration : [] int, idx : hole ) : bool {
  var good = true;
  for adj in graph[idx] {
    if adj >= idx then continue;
    if abs( configuration[idx] - configuration[adj] ) <= 1 {
      good = false;
      break;
    }
  }

  return good;
}

proc solve( configuration : [] int, pegs : domain(int), idx : hole = A ) : bool {
  for value in pegs {
    configuration[idx] = value;
    if check( configuration, idx ) {
      if idx < holes.size {
        var prePegs = pegs;
        if solve( configuration, prePegs - value, idx + 1 ){
          return true;
        }
      } else {
        return true;
      }
    }
  }
  configuration[idx] = starting;
  return false;
}

proc printBoard( configuration : [] int ){
return
"\n       " + configuration[A] + "   " + configuration[B]+ "\n" +
"      /|\\ /|\\ \n"+
"     / | X | \\ \n"+
"    /  |/ \\|  \\ \n"+
"   " + configuration[C] +" - " + configuration[D] + " - " + configuration[E] + " - " + configuration[F] + " \n"+
"    \\  |\\ /|  / \n"+
"     \\ | X | / \n"+
"      \\|/ \\|/ \n"+
"       " + configuration[G] + "   " + configuration[H]+ "\n";

}

proc main(){
  var configuration : [holes] int;
  for idx in holes do configuration[idx] = starting;

  var pegs : domain(int) = {1,2,3,4,5,6,7,8};
  solve( configuration, pegs );

  writeln( printBoard( configuration ) );

}


void main() @safe {
    import std.stdio, std.math, std.algorithm, std.traits, std.string;

    enum Peg { A, B, C, D, E, F, G, H }
    immutable Peg[2][15] connections =
            [[Peg.A, Peg.C], [Peg.A, Peg.D], [Peg.A, Peg.E],
             [Peg.B, Peg.D], [Peg.B, Peg.E], [Peg.B, Peg.F],
             [Peg.C, Peg.D], [Peg.D, Peg.E], [Peg.E, Peg.F],
             [Peg.G, Peg.C], [Peg.G, Peg.D], [Peg.G, Peg.E],
             [Peg.H, Peg.D], [Peg.H, Peg.E], [Peg.H, Peg.F]];

    immutable board = r"
        A   B
       /|\ /|\
      / | X | \
     /  |/ \|  \
    C - D - E - F
     \  |\ /|  /
      \ | X | /
       \|/ \|/
        G   H";

    Peg[EnumMembers!Peg.length] perm = [EnumMembers!Peg];
    do if (connections[].all!(con => abs(perm[con[0]] - perm[con[1]]) > 1))
        return board.tr("ABCDEFGH", "%(%d%)".format(perm)).writeln;
    while (perm[].nextPermutation);
}


# It solved if connected A and B, connected G and H (according to the video).

# require HLPsolver

adjacent = for i <- -2..2, j <- -2..2, not(i in -1..1 and j in -1..1), do: {i,j}
layout = ~S"""
       A - B
      /|\ /|\
     / | X | \
    /  |/ \|  \
   C - D - E - F
    \  |\ /|  /
     \ | X | /
      \|/ \|/
       G - H
"""
board = """
  . 0 0 .
  0 1 0 0
  . 0 0 .
"""
HLPsolver.solve(board, adjacent, false)
|> Enum.sort |> Enum.map(fn {_,cell} -> cell.value end)
|> Enum.zip(~w[A B C D E F G H])
|> Enum.reduce(layout, fn {n,c},acc -> String.replace(acc, c, to_string(n)) end)
|> IO.puts


USING: assocs interpolate io kernel math math.combinatorics
math.ranges math.parser multiline pair-rocket sequences
sequences.generalizations ;

STRING: diagram
    ${}   ${}
   /|\ /|\
  / | X | \
 /  |/ \|  \
${} - ${} - ${} - ${}
 \  |\ /|  /
  \ | X | /
   \|/ \|/
    ${}   ${}
;

CONSTANT: adjacency
H{
    0 => { 2 3 4 }
    1 => { 3 4 5 }
    2 => { 0 3 6 }
    3 => { 0 1 2 4 6 7 }
    4 => { 0 1 3 5 6 7 }
    5 => { 1 4 7 }
    6 => { 2 3 4 }
    7 => { 3 4 5 }
}

: any-consecutive? ( seq n -- ? ) [ - abs 1 = ] curry any? ;

: neighbors ( elt seq i -- seq elt )
    adjacency at swap nths swap ;

: solution? ( permutation-seq -- ? )
    dup [ neighbors any-consecutive? ] with find-index nip not ;

: find-solution ( -- seq )
    8 [1,b] [ solution? ] find-permutation ;

: display-solution ( seq -- )
    [ number>string ] map 8 firstn diagram interpolate>string
    print ;

: main ( -- ) find-solution display-solution ;

MAIN: main


! This is free and unencumbered software released into the public domain,
! via the Unlicense.
! For more information, please refer to <http://unlicense.org/>

program no_connection_puzzle

  implicit none

  ! The names of the holes.
  integer, parameter :: a = 1
  integer, parameter :: b = 2
  integer, parameter :: c = 3
  integer, parameter :: d = 4
  integer, parameter :: e = 5
  integer, parameter :: f = 6
  integer, parameter :: g = 7
  integer, parameter :: h = 8

  integer :: holes(a:h)

  call find_solutions (holes, a)

contains

  recursive subroutine find_solutions (holes, current_hole_index)
    integer, intent(inout) :: holes(a:h)
    integer, intent(in) :: current_hole_index

    integer :: peg_number

    ! Recursively construct and print possible solutions, quitting
    ! any partial solution that does not satisfy constraints.
    do peg_number = 1, 8
       holes(current_hole_index) = peg_number
       if (satisfies_the_constraints (holes, current_hole_index)) then
          if (current_hole_index == h) then
             call print_solution (holes)
             write (*, '()')
          else
             call find_solutions (holes, current_hole_index + 1)
          end if
       end if
    end do
  end subroutine find_solutions

  function satisfies_the_constraints (holes, i) result (satisfies)
    integer, intent(inout) :: holes(a:h)
    integer, intent(in) :: i    ! Where the new peg goes.
    logical :: satisfies

    integer :: j

    ! The most recently inserted peg must not be a duplicate of one
    ! already inserted.
    satisfies = all (holes(a : i - 1) /= holes(i))

    if (satisfies) then
       ! ‘Fill’ the unfilled holes with fake pegs that cause
       ! differences with them always to be larger than 1.
       do j = i + 1, h
          holes(j) = 100 * j
       end do

       ! Check that the differences are satisfactory.
       satisfies = 1 < abs (holes(a) - holes(c)) .and.     &
            &      1 < abs (holes(a) - holes(d)) .and.     &
            &      1 < abs (holes(a) - holes(e)) .and.     &
            &      1 < abs (holes(c) - holes(g)) .and.     &
            &      1 < abs (holes(d) - holes(g)) .and.     &
            &      1 < abs (holes(e) - holes(g)) .and.     &
            &      1 < abs (holes(b) - holes(d)) .and.     &
            &      1 < abs (holes(b) - holes(e)) .and.     &
            &      1 < abs (holes(b) - holes(f)) .and.     &
            &      1 < abs (holes(d) - holes(h)) .and.     &
            &      1 < abs (holes(e) - holes(h)) .and.     &
            &      1 < abs (holes(f) - holes(h)) .and.     &
            &      1 < abs (holes(c) - holes(d)) .and.     &
            &      1 < abs (holes(d) - holes(e)) .and.     &
            &      1 < abs (holes(e) - holes(f))
    end if
  end function satisfies_the_constraints

  subroutine print_solution (holes)
    integer, intent(in) :: holes(a:h)

    write (*, '(I5, I4)') holes(a), holes(b)
    write (*, '("   /│\ /│\")')
    write (*, '("  / │ X │ \")')
    write (*, '(" /  │/ \│  \")')
    write (*, '(3(I1, "───"), I1)') holes(c), holes(d), holes(e), holes(f)
    write (*, '(" \  │\ /│  /")')
    write (*, '("  \ │ X │ /")')
    write (*, '("   \│/ \│/")')
    write (*, '(I5, I4)') holes(g), holes(h)
  end subroutine print_solution

end program no_connection_puzzle


package main

import (
	"fmt"
	"strings"
)

func main() {
	p, tests, swaps := Solution()
	fmt.Println(p)
	fmt.Println("Tested", tests, "positions and did", swaps, "swaps.")
}

// Holes A=0, B=1, …, H=7
// With connections:
const conn = `
       A   B
      /|\ /|\
     / | X | \
    /  |/ \|  \
   C - D - E - F
    \  |\ /|  /
     \ | X | /
      \|/ \|/
       G   H`

var connections = []struct{ a, b int }{
	{0, 2}, {0, 3}, {0, 4}, // A to C,D,E
	{1, 3}, {1, 4}, {1, 5}, // B to D,E,F
	{6, 2}, {6, 3}, {6, 4}, // G to C,D,E
	{7, 3}, {7, 4}, {7, 5}, // H to D,E,F
	{2, 3}, {3, 4}, {4, 5}, // C-D, D-E, E-F
}

type pegs [8]int

// Valid checks if the pegs are a valid solution.
// If the absolute difference between any pair of connected pegs is
// greater than one it is a valid solution.
func (p *pegs) Valid() bool {
	for _, c := range connections {
		if absdiff(p[c.a], p[c.b]) <= 1 {
			return false
		}
	}
	return true
}

// Solution is a simple recursive brute force solver,
// it stops at the first found solution.
// It returns the solution, the number of positions tested,
// and the number of pegs swapped.
func Solution() (p *pegs, tests, swaps int) {
	var recurse func(int) bool
	recurse = func(i int) bool {
		if i >= len(p)-1 {
			tests++
			return p.Valid()
		}
		// Try each remain peg from p[i:] in p[i]
		for j := i; j < len(p); j++ {
			swaps++
			p[i], p[j] = p[j], p[i]
			if recurse(i + 1) {
				return true
			}
			p[i], p[j] = p[j], p[i]
		}
		return false
	}
	p = &pegs{1, 2, 3, 4, 5, 6, 7, 8}
	recurse(0)
	return
}

func (p *pegs) String() string {
	return strings.Map(func(r rune) rune {
		if 'A' <= r && r <= 'H' {
			return rune(p[r-'A'] + '0')
		}
		return r
	}, conn)
}

func absdiff(a, b int) int {
	if a > b {
		return a - b
	}
	return b - a
}


import java.util.stream.Collectors
import java.util.stream.IntStream

class NoConnection {
    // adopted from Go
    static int[][] links = [
            [2, 3, 4], // A to C,D,E
            [3, 4, 5], // B to D,E,F
            [2, 4],    // D to C, E
            [5],       // E to F
            [2, 3, 4], // G to C,D,E
            [3, 4, 5], // H to D,E,F
    ]

    static int[] pegs = new int[8]

    static void main(String[] args) {
        List<Integer> vals = IntStream.range(1, 9)
                .mapToObj({ it })
                .collect(Collectors.toList())

        while (true) {
            Collections.shuffle(vals)
            for (int i = 0; i < pegs.length; i++) {
                pegs[i] = vals.get(i)
            }
            if (solved()) {
                break
            }
        }

        printResult()
    }

    static boolean solved() {
        for (int i = 0; i < links.length; i++) {
            for (int peg : links[i]) {
                if (Math.abs(pegs[i] - peg) == 1) {
                    return false
                }
            }
        }
        return true
    }

    static void printResult() {
        println("  ${pegs[0]} ${pegs[1]}")
        println("${pegs[2]} ${pegs[3]} ${pegs[4]} ${pegs[5]}")
        println("  ${pegs[6]} ${pegs[7]}")
    }
}


import Data.List (permutations)

solution :: [Int]
solution@(a : b : c : d : e : f : g : h : _) =
  head $
    filter isSolution (permutations [1 .. 8])
  where
    isSolution :: [Int] -> Bool
    isSolution (a : b : c : d : e : f : g : h : _) =
      all ((> 1) . abs) $
        zipWith
          (-)
          [a, c, g, e, a, c, g, e, b, d, h, f, b, d, h, f]
          [d, d, d, d, c, g, e, a, e, e, e, e, d, h, f, b]

main :: IO ()
main =
  (putStrLn . unlines) $
    unlines
      ( zipWith
          (\x y -> x : (" = " <> show y))
          ['A' .. 'H']
          solution
      ) :
    ( rightShift . unwords . fmap show
        <$> [[], [a, b], [c, d, e, f], [g, h]]
    )
  where
    rightShift s
      | length s > 3 = s
      | otherwise = "  " <> s


holes=:;:'A B C D E F G H'

connections=:".;._2]0 :0
 holes e.;:'C D E'          NB. A
 holes e.;:'D E F'          NB. B
 holes e.;:'A D G'          NB. C
 holes e.;:'A B C E G H'    NB. D
 holes e.;:'A B D F G H'    NB. E
 holes e.;:'B E H'          NB. F
 holes e.;:'C D E'          NB. G
 holes e.;:'D E F'          NB. H
)
assert (-:|:) connections NB. catch typos

pegs=: 1+(A.&i.~ !)8

attempt=: [: <./@(-.&0)@,@:| connections * -/~

box=:0 :0
        A   B
       /|\ /|\
      / | X | \
     /  |/ \|  \
    C - D - E - F
     \  |\ /|  /
      \ | X | /
       \|/ \|/
        G   H
)

disp=:verb define
  rplc&(,holes;&":&>y) box
)


import static java.lang.Math.abs;
import java.util.*;
import static java.util.stream.Collectors.toList;
import static java.util.stream.IntStream.range;

public class NoConnection {

    // adopted from Go
    static int[][] links = {
        {2, 3, 4}, // A to C,D,E
        {3, 4, 5}, // B to D,E,F
        {2, 4},    // D to C, E
        {5},       // E to F
        {2, 3, 4}, // G to C,D,E
        {3, 4, 5}, // H to D,E,F
    };

    static int[] pegs = new int[8];

    public static void main(String[] args) {

        List<Integer> vals = range(1, 9).mapToObj(i -> i).collect(toList());
        do {
            Collections.shuffle(vals);
            for (int i = 0; i < pegs.length; i++)
                pegs[i] = vals.get(i);

        } while (!solved());

        printResult();
    }

    static boolean solved() {
        for (int i = 0; i < links.length; i++)
            for (int peg : links[i])
                if (abs(pegs[i] - peg) == 1)
                    return false;
        return true;
    }

    static void printResult() {
        System.out.printf("  %s %s%n", pegs[0], pegs[1]);
        System.out.printf("%s %s %s %s%n", pegs[2], pegs[3], pegs[4], pegs[5]);
        System.out.printf("  %s %s%n", pegs[6], pegs[7]);
    }
}


(() => {
    'use strict';

    // -------------- NO CONNECTION PUZZLE ---------------

    // solvedPuzzle :: () -> [Int]
    const solvedPuzzle = () => {

        // universe :: [[Int]]
        const universe = permutations(enumFromTo(1)(8));

        // isSolution :: [Int] -> Bool
        const isSolution = ([a, b, c, d, e, f, g, h]) =>
            all(x => abs(x) > 1)([
                a - d, c - d, g - d, e - d, a - c, c - g,
                g - e, e - a, b - e, d - e, h - e, f - e,
                b - d, d - h, h - f, f - b
            ]);

        return universe[
            until(i => isSolution(universe[i]))(
                succ
            )(0)
        ];
    }

    // ---------------------- TEST -----------------------
    const main = () => {
        const
            firstSolution = solvedPuzzle(),
            [a, b, c, d, e, f, g, h] = firstSolution;

        return unlines(
            zipWith(
                a => n => a + ' = ' + n.toString()
            )(enumFromTo('A')('H'))(firstSolution)
            .concat([
                [],
                [a, b],
                [c, d, e, f],
                [g, h]
            ].map(
                xs => unwords(xs.map(show))
                .padStart(5, ' ')
            ))
        );
    }

    // ---------------- GENERIC FUNCTIONS ----------------

    // abs :: Num -> Num
    const abs =
        // Absolute value of a given number - without the sign.
        Math.abs;

    // all :: (a -> Bool) -> [a] -> Bool
    const all = p =>
        // True if p(x) holds for every x in xs.
        xs => [...xs].every(p);

    // compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
    const compose = (...fs) =>
        // A function defined by the right-to-left
        // composition of all the functions in fs.
        fs.reduce(
            (f, g) => x => f(g(x)),
            x => x
        );

    // enumFromTo :: Enum a => a -> a -> [a]
    const enumFromTo = m => n => {
        const [x, y] = [m, n].map(fromEnum),
            b = x + (isNaN(m) ? 0 : m - x);
        return Array.from({
            length: 1 + (y - x)
        }, (_, i) => toEnum(m)(b + i));
    };

    // fromEnum :: Enum a => a -> Int
    const fromEnum = x =>
        typeof x !== 'string' ? (
            x.constructor === Object ? (
                x.value
            ) : parseInt(Number(x))
        ) : x.codePointAt(0);

    // length :: [a] -> Int
    const length = xs =>
        // Returns Infinity over objects without finite
        // length. This enables zip and zipWith to choose
        // the shorter argument when one is non-finite,
        // like cycle, repeat etc
        'GeneratorFunction' !== xs.constructor
        .constructor.name ? (
            xs.length
        ) : Infinity;

    // list :: StringOrArrayLike b => b -> [a]
    const list = xs =>
        // xs itself, if it is an Array,
        // or an Array derived from xs.
        Array.isArray(xs) ? (
            xs
        ) : Array.from(xs || []);

    // permutations :: [a] -> [[a]]
    const permutations = xs => (
        ys => ys.reduceRight(
            (a, y) => a.flatMap(
                ys => Array.from({
                    length: 1 + ys.length
                }, (_, i) => i)
                .map(n => ys.slice(0, n)
                    .concat(y)
                    .concat(ys.slice(n))
                )
            ), [
                []
            ]
        )
    )(list(xs));

    // show :: a -> String
    const show = x =>
        JSON.stringify(x);

    // succ :: Enum a => a -> a
    const succ = x =>
        1 + x;

    // take :: Int -> [a] -> [a]
    // take :: Int -> String -> String
    const take = n =>
        // The first n elements of a list,
        // string of characters, or stream.
        xs => 'GeneratorFunction' !== xs
        .constructor.constructor.name ? (
            xs.slice(0, n)
        ) : [].concat.apply([], Array.from({
            length: n
        }, () => {
            const x = xs.next();
            return x.done ? [] : [x.value];
        }));

    // toEnum :: a -> Int -> a
    const toEnum = e =>
        // The first argument is a sample of the type
        // allowing the function to make the right mapping
        x => ({
            'number': Number,
            'string': String.fromCodePoint,
            'boolean': Boolean,
            'object': v => e.min + v
        } [typeof e])(x);

    // unlines :: [String] -> String
    const unlines = xs =>
        // A single string formed by the intercalation
        // of a list of strings with the newline character.
        xs.join('\n');

    // until :: (a -> Bool) -> (a -> a) -> a -> a
    const until = p =>
        f => x => {
            let v = x;
            while (!p(v)) v = f(v);
            return v;
        };

    // unwords :: [String] -> String
    const unwords = xs =>
        // A space-separated string derived
        // from a list of words.
        xs.join(' ');

    // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
    const zipWith = f =>
        // Use of `take` and `length` here allows
        // zipping with non-finite lists
        // i.e. generators like cycle, repeat, iterate.
        xs => ys => {
            const n = Math.min(length(xs), length(ys));
            return Infinity > n ? (
                (([as, bs]) => Array.from({
                    length: n
                }, (_, i) => f(as[i])(
                    bs[i]
                )))([xs, ys].map(
                    compose(take(n), list)
                ))
            ) : zipWithGen(f)(xs)(ys);
        };

    return main();
})();


# Short-circuit determination of whether (a|condition)
# is true for all a in array:
def forall(array; condition):
  def check:
    . as $ix
    | if $ix == (array|length) then true
      elif (array[$ix] | condition) then ($ix + 1) | check
      else false
      end;
  0 | check;

# permutations of 0 .. (n-1)
def permutations(n):
  # Given a single array, generate a stream by inserting n at different positions:
  def insert(m;n):
     if m >= 0 then (.[0:m] + [n] + .[m:]), insert(m-1;n) else empty end;
  if n==0 then []
  elif n == 1 then [1]
  else
    permutations(n-1) | insert(n-1; n)
  end;

# Count the number of items in a stream
def count(f): reduce f as $_ (0; .+1);


using Combinatorics

const HOLES = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
const PEGS = [1, 2, 3, 4, 5, 6, 7, 8]
const EDGES = [('A', 'C'), ('A', 'D'), ('A', 'E'),
               ('B', 'D'), ('B', 'E'), ('B', 'F'),
               ('C', 'G'), ('C', 'D'), ('D', 'G'),
               ('D', 'E'), ('D', 'H'), ('E', 'F'),
               ('E', 'G'), ('E', 'H'), ('F', 'H')]

goodperm(p) = all(e->abs(p[e[1]-'A'+1] - p[e[2]-'A'+1]) > 1, EDGES)

goodplacements() = [p for p in permutations(PEGS) if goodperm(p)]

const BOARD = raw"""
        A   B
       /|\ /|\
      / | X | \
     /  |/ \|  \
    C - D - E - F
     \  |\ /|  /
      \ | X | /
       \|/ \|/
        G   H
"""

function printsolutions()
    solutions = goodplacements()
    println("Found $(length(solutions)) solutions.")
    for soln in solutions
        board = BOARD
        for (i, n) in enumerate(soln)
            board = replace(board, string('A' + i - 1) => string(n))
        end
        println(board); exit(1) # remove this exit for all solutions
    end
end

printsolutions()


// version 1.2.0

import kotlin.math.abs

// Holes A=0, B=1, …, H=7
// With connections:
const val conn = """
       A   B
      /|\ /|\
     / | X | \
    /  |/ \|  \
   C - D - E - F
    \  |\ /|  /
     \ | X | /
      \|/ \|/
       G   H
"""

val connections = listOf(
    0 to 2, 0 to 3, 0 to 4,   // A to C, D, E
    1 to 3, 1 to 4, 1 to 5,   // B to D, E, F
    6 to 2, 6 to 3, 6 to 4,   // G to C, D, E
    7 to 3, 7 to 4, 7 to 5,   // H to D, E, F
    2 to 3, 3 to 4, 4 to 5    // C-D, D-E, E-F
)

// 'isValid' checks if the pegs are a valid solution.
// If the absolute difference between any pair of connected pegs is
// greater than one it is a valid solution.
fun isValid(pegs: IntArray): Boolean {
   for ((a, b) in connections) {
       if (abs(pegs[a] - pegs[b]) <= 1) return false
   }
   return true
}

fun swap(pegs: IntArray, i: Int, j: Int) {
    val tmp = pegs[i]
    pegs[i] = pegs[j]
    pegs[j] = tmp
}

// 'solve' is a simple recursive brute force solver,
// it stops at the first found solution.
// It returns the solution, the number of positions tested,
// and the number of pegs swapped.

fun solve(): Triple<IntArray, Int, Int> {
    val pegs = IntArray(8) { it + 1 }
    var tests = 0
    var swaps = 0

    fun recurse(i: Int): Boolean {
        if (i >= pegs.size - 1) {
            tests++
            return isValid(pegs)
        }
        // Try each remaining peg from pegs[i] onwards
        for (j in i until pegs.size) {
            swaps++
            swap(pegs, i, j)
            if (recurse(i + 1)) return true
            swap(pegs, i, j)
        }
        return false
    }

    recurse(0)
    return Triple(pegs, tests, swaps)
}

fun pegsAsString(pegs: IntArray): String {
    val ca = conn.toCharArray()
    for ((i, c) in ca.withIndex()) {
        if (c in 'A'..'H') ca[i] = '0' + pegs[c - 'A']
    }
    return String(ca)
}

fun main(args: Array<String>) {
    val (p, tests, swaps) = solve()
    println(pegsAsString(p))
    println("Tested $tests positions and did $swaps swaps.")
}


Module no_connection_puzzle {
      \\ Holes
      Inventory Connections="A":="CDE","B":="DEF","C":="ADG", "D":="ABCEGH"
      Append Connections, "E":="ABDFGH","F":="HEB", "G":="CDE","H":="DEF"
      Inventory ToDelete, Solutions
      \\ eliminate double connnections
      con=each(Connections)
      While con {
            m$=eval$(con, con^)
            c$=eval$(con)
            If c$="*" Then continue
            For i=1 to len(C$) {
                 d$=mid$(c$,i,1)
                 r$=Filter$(Connections$(d$), m$)
                 If r$<>"" Then  {
                         Return connections, d$:=r$
                  }  else   {
                        If m$=connections$(d$) Then {
                              Return connections, d$:="*"  : If not exist(todelete, d$)  Then  Append todelete, d$
                        }
                  }
            }
      }
      con=each(todelete)
      While con {
            Delete Connections, eval$(con)
      }
      Inventory Holes
      For i=0 to 7 : Append Holes, Chr$(65+i):=i : Next i
      CheckValid=lambda Holes, Connections (a$, arr) -> {
            val=Array(arr, Holes(a$))
            con$=Connections$(a$)
            res=True
            For i=1 to Len(con$) {
                 If Abs(Array(Arr, Holes(mid$(con$,i,1)))-val)<2 Then res=False: Exit
            }
            =res
      }
      a=(1,2,3,4,5,6,7,8)
      h=(,)
      solution=(,)
      done=False
      counter=0
      Print "Wait..."
      P(h, a)
      sol=Each(Solutions)
      While sol {
            Print "Solution:";sol^+1
            Disp(Eval(Solutions))
            aa$=Key$
      }
      Sub P(h, a)
      If len(a)<=1 Then process(cons(h, a)) : Exit Sub
      local b=cons(a)
      For i=1 to len(b) {
                  b=cons(cdr(b),car(b))
                  P(cons(h,car(b)), cdr(b))
      }
      End Sub
      Sub Process(a)
            counter++
            Print counter
            If keypress(32) Then {
            local  sol=Each(Solutions)
                        aa$=Key$
                        While sol {
                                    Print "Solution:";sol^+1
                                    Disp(Eval(Solutions))
                                    aa$=Key$
                        }
            }
            hole=each(Connections)
            done=True
            While hole {
                  If not CheckValid(Eval$(hole, hole^), a) Then done=False : Exit
            }
            If done Then Append Solutions, Len(Solutions):=a : Print a
      End Sub
      Sub Disp(a)
            Print format$("    {0}   {1}", array(a), array(a,1))
            Print "   /|\ /|\"
            Print "  / | X | \"
            Print " /  |/ \|  \"
            Print Format$("{0} - {1} - {2} - {3}", array(a,2),array(a,3), array(a,4), array(a,5))
            Print " \  |\ /|  /"
            Print "  \ | X | /"
            Print "   \|/ \|/"
            Print Format$("    {0}   {1}", array(a,6), array(a,7))
      End Sub
}
no_connection_puzzle


import strformat

const Connections = [(1, 3), (1, 4), (1, 5),  # A to C, D, E
                     (2, 4), (2, 5), (2, 6),  # B to D, E, F
                     (7, 3), (7, 4), (7, 5),  # G to C, D, E
                     (8, 4), (8, 5), (8, 6),  # H to D, E, F
                     (3, 4), (4, 5), (5, 6)]  # C-D, D-E, E-F

type
  Peg = 1..8
  Pegs = array[1..8, Peg]

func valid(pegs: Pegs): bool =
  for (src, dst) in Connections:
    if abs(pegs[src] - pegs[dst]) == 1:
      return false
  result = true

proc print(pegs: Pegs; num: Positive) =
  echo &"----- {num} -----"
  echo &"  {pegs[1]} {pegs[2]}"
  echo &"{pegs[3]} {pegs[4]} {pegs[5]} {pegs[6]}"
  echo &"  {pegs[7]} {pegs[8]}"
  echo()

proc findSolution(pegs: var Pegs; left, right: Natural; solCount = 0): Natural =
  var solCount = solCount
  if left == right:
    if pegs.valid():
      inc solCount
      pegs.print(solCount)
  else:
    for i in left..right:
      swap pegs[left], pegs[i]
      solCount = pegs.findSolution(left + 1, right, solCount)
      swap pegs[left], pegs[i]
  result = solCount

when isMainModule:

  var pegs = [Peg 1, 2, 3, 4, 5, 6, 7, 8]
  discard pegs.findSolution(1, 8)


with javascript_semantics
constant txt = """
        A   B
       /|\ /|\
      / | X | \
     /  |/ \|  \
    C - D - E - F
     \  |\ /|  /
      \ | X | /
       \|/ \|/
        G   H
"""
--constant links = "CA DA DB DC EA EB ED FB FE GC GD GE HD HE HF"
constant links = {"","","A","ABC","ABD","BE","CDE","DEF"}

function solve(sequence s, integer idx, sequence part)
    object res
    integer v, p
    for i=1 to length(s) do
        v = s[i]
        for j=1 to length(links[idx]) do
            p = links[idx][j]-'@'
            if abs(v-part[p])<2 then v=0 exit end if
        end for
        if v then
            if length(s)=1 then return part&v end if
            res = solve(s[1..i-1]&s[i+1..$],idx+1,part&v)
            if sequence(res) then return res end if
        end if
    end for
    return 0
end function

printf(1,substitute_all(txt,"ABCDEFGH",solve("12345678",1,"")))


:- use_module(library(clpfd)).

edge(a, c).
edge(a, d).
edge(a, e).
edge(b, d).
edge(b, e).
edge(b, f).
edge(c, d).
edge(c, g).
edge(d, e).
edge(d, g).
edge(d, h).
edge(e, f).
edge(e, g).
edge(e, h).
edge(f, h).

connected(A, B) :-
	(   edge(A,B); edge(B, A)).

no_connection_puzzle(Vs) :-
	% construct the arranged list of the nodes
	bagof(A, B^(edge(A,B); edge(B, A)), Lst),
	sort(Lst, L),
	length(L, Len),

	% construct the list of the values
	length(Vs, Len),
	Vs ins 1..Len,
	all_distinct(Vs),

	% two connected nodes must have values different for more than 1
	set_constraints(L, Vs),
	label(Vs).

set_constraints([], []).

set_constraints([H | T], [VH | VT]) :-
	set_constraint(H, T, VH, VT),
	set_constraints(T, VT).

set_constraint(_, [], _, []).
set_constraint(H, [H1 | T1], V, [VH | VT]) :-
	connected(H, H1),
	(   V - VH #> 1; VH - V #> 1),
	set_constraint(H, T1, V, VT).

set_constraint(H, [H1 | T1], V, [_VH | VT]) :-
	\+connected(H, H1),
	set_constraint(H, T1, V, VT).


from __future__ import print_function
from itertools import permutations
from enum import Enum

A, B, C, D, E, F, G, H = Enum('Peg', 'A, B, C, D, E, F, G, H')

connections = ((A, C), (A, D), (A, E),
               (B, D), (B, E), (B, F),
               (G, C), (G, D), (G, E),
               (H, D), (H, E), (H, F),
               (C, D), (D, E), (E, F))

def ok(conn, perm):
    """Connected numbers ok?"""
    this, that = (c.value - 1 for c in conn)
    return abs(perm[this] - perm[that]) != 1

def solve():
    return [perm for perm in permutations(range(1, 9))
            if all(ok(conn, perm) for conn in connections)]

if __name__ == '__main__':
    solutions = solve()
    print("A, B, C, D, E, F, G, H =", ', '.join(str(i) for i in solutions[0]))


#lang racket
;; Solve the no connection puzzle. Tim Brown Oct. 2014

;; absolute difference of a and b if they are both true
(define (and- a b) (and a b (abs (- a b))))

;; Finds the differences of all established connections in the network
(define (network-diffs (A #f) (B #f) (C #f) (D #f) (E #f) (F #f) (G #f) (H #f))
  (list (and- A C) (and- A D) (and- A E)
        (and- B D) (and- B E) (and- B F)
        (and- C D) (and- C G)
        (and- D E) (and- D G) (and- D H)
        (and- E F) (and- E G) (and- E H)
        (and- F G)))

;; Make sure there is “no connection” in the network N; return N if good
(define (good-network? N)
  (and (for/and ((d (filter values (apply network-diffs N)))) (> d 1)) N))

;; possible optimisation is to reverse the arguments to network-diffs, reverse the return value from
;; this function and make this a cons but we're pretty quick here as it is.
(define (find-good-network pegs (n/w null))
  (if (null? pegs) n/w
      (for*/or ((p pegs))
        (define n/w+ (append n/w (list p)))
        (and (good-network? n/w+)
             (find-good-network (remove p pegs =) n/w+)))))

(define (render-puzzle pzl)
  (apply printf (regexp-replace* "O" #<<EOS
    O   O
   /|\ /|\
  / | X | \
 /  |/ \|  \
O - O - O - O
 \  |\ /|  /
  \ | X | /
   \|/ \|/
    O   O~%
EOS
                                 "~a") pzl))

(render-puzzle (find-good-network '(1 2 3 4 5 6 7 8)))


my @adjacent = gather -> $y, $x {
    take [$y,$x] if abs($x|$y) > 2;
} for flat -5 .. 5 X -5 .. 5;

solveboard q:to/END/;
    . _ . . _ .
    . . . . . .
    _ . _ 1 . _
    . . . . . .
    . _ . . _ .
    END

sub solveboard($board) {
    my $max = +$board.comb(/\w+/);
    my $width = $max.chars;

    my @grid;
    my @known;
    my @neigh;
    my @degree;

    @grid = $board.lines.map: -> $line {
        [ $line.words.map: { /^_/ ?? 0 !! /^\./ ?? Rat !! $_ } ]
    }

    sub neighbors($y,$x --> List) {
        eager gather for @adjacent {
            my $y1 = $y + .[0];
            my $x1 = $x + .[1];
            take [$y1,$x1] if defined @grid[$y1][$x1];
        }
    }

    for ^@grid -> $y {
        for ^@grid[$y] -> $x {
            if @grid[$y][$x] -> $v {
                @known[$v] = [$y,$x];
            }
            if @grid[$y][$x].defined {
                @neigh[$y][$x] = neighbors($y,$x);
                @degree[$y][$x] = +@neigh[$y][$x];
            }
        }
    }
    print "\e[0H\e[0J";

    my $tries = 0;

    try_fill 1, @known[1];

    sub try_fill($v, $coord [$y,$x] --> Bool) {
        return True if $v > $max;
        $tries++;

        my $old = @grid[$y][$x];

        return False if +$old and $old != $v;
        return False if @known[$v] and @known[$v] !eqv $coord;

        @grid[$y][$x] = $v;               # conjecture grid value

        print "\e[0H";                    # show conjectured board
        for @grid -> $r {
            say do for @$r {
                when Rat { ' ' x $width }
                when 0   { '_' x $width }
                default  { .fmt("%{$width}d") }
            }
        }

        my @neighbors = @neigh[$y][$x][];

        my @degrees;
        for @neighbors -> \n [$yy,$xx] {
            my $d = --@degree[$yy][$xx];  # conjecture new degrees
            push @degrees[$d], n;         # and categorize by degree
        }

        for @degrees.grep(*.defined) -> @ties {
            for @ties.reverse {           # reverse works better for this hidato anyway
                return True if try_fill $v + 1, $_;
            }
        }

        for @neighbors -> [$yy,$xx] {
            ++@degree[$yy][$xx];          # undo degree conjectures
        }

        @grid[$y][$x] = $old;             # undo grid value conjecture
        return False;
    }

    say "$tries tries";
}


Red ["Solve the no connection puzzle"]

points: [a b c d e f g h]
	; 'links' series will be scanned by pairs: [a c], [a d] etc.
links: [a c a d a e b d b e b f c d c g d e d g d h e f e g e h f h]
allpegs: [1 2 3 4 5 6 7 8]

	; check if two points are connected (then game is lost) i.e.
	; both are have a value (not zero) and absolute difference is 1
connected: func [x y] [all [
	x * y <> 0
	1 = absolute (x - y)
]]
	; a list of points is valid if no connexion is found
isvalid: function [pegs [block!]] [
	; assign pegs values to points, or 0 for remaining points
	set points append/dup copy pegs 0 8
	foreach [x y] links [if connected get x get y [return false]]
	true
]
	; recursively build a list of up to 8 valid points
check: function [pegs [block!]] [
	if isvalid pegs [
		rest: difference allpegs pegs
		either empty? rest [
			print rejoin ["Here is a solution: " pegs]
			halt ; comment this line to get all solutions
		][
			foreach peg rest [check append copy pegs peg]
		]
	]
]
	; start with and empty list
check []


/*REXX program  solves  the  "no─connection"  puzzle   (the puzzle has eight pegs).     */
parse arg limit .    /*number of solutions wanted.*/   /* ╔═══════════════════════════╗ */
if limit=='' | limit==","  then limit= 1               /* ║          A    B           ║ */
                                                       /* ║         /│\  /│\          ║ */
@.  =                                                  /* ║        / │ \/ │ \         ║ */
@.1 = 'A   C D E'                                      /* ║       /  │ /\ │  \        ║ */
@.2 = 'B   D E F'                                      /* ║      /   │/  \│   \       ║ */
@.3 = 'C   A D G'                                      /* ║     C────D────E────F      ║ */
@.4 = 'D   A B C E G'                                  /* ║      \   │\  /│   /       ║ */
@.5 = 'E   A B D F H'                                  /* ║       \  │ \/ │  /        ║ */
@.6 = 'F   B E H'                                      /* ║        \ │ /\ │ /         ║ */
@.7 = 'G   C D E'                                      /* ║         \│/  \│/          ║ */
@.8 = 'H   D E F'                                      /* ║          G    H           ║ */
cnt= 0                                                 /* ╚═══════════════════════════╝ */
                  do pegs=1  while  @.pegs\=='';    _= word(@.pegs, 1)
                  subs= 0
                             do #=1  for  words(@.pegs) -1  /*create list of node paths.*/
                             __= word(@.pegs, # + 1);    if __>_  then iterate
                             subs= subs + 1;             !._.subs= __
                             end  /*#*/
                  !._.0= subs                    /*assign the number of the node paths. */
                  end   /*pegs*/
pegs= pegs - 1                                   /*the number of pegs to be seated.     */
                  _= '    '                      /*_   is used for indenting the output.*/
       do               a=1  for pegs;     if ?('A')  then iterate
         do             b=1  for pegs;     if ?('B')  then iterate
           do           c=1  for pegs;     if ?('C')  then iterate
             do         d=1  for pegs;     if ?('D')  then iterate
               do       e=1  for pegs;     if ?('E')  then iterate
                 do     f=1  for pegs;     if ?('F')  then iterate
                   do   g=1  for pegs;     if ?('G')  then iterate
                     do h=1  for pegs;     if ?('H')  then iterate
                     say _ 'a='a _ "b="||b _ 'c='c _ "d="d _ 'e='e _ "f="f _ 'g='g _ "h="h
                     cnt= cnt + 1;         if cnt==limit  then leave a
                     end   /*h*/
                   end     /*g*/
                 end       /*f*/
               end         /*e*/
             end           /*d*/
           end             /*c*/
         end               /*b*/
       end                 /*a*/
say                                              /*display a blank line to the terminal.*/
s= left('s', cnt\==1)                            /*handle the case of plurals  (or not).*/
say 'found '     cnt     " solution"s'.'         /*display the number of solutions found*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
?: parse arg node;           nn= value(node)
   nH= nn+1
             do cn=c2d('A')  to c2d(node)-1;   if value( d2c(cn) )==nn  then return 1
             end   /*cn*/                       /* [↑]  see if there any are duplicates.*/
   nL= nn-1
             do ch=1  for !.node.0              /* [↓]  see if there any  ¬= ±1  values.*/
             $= !.node.ch;       fn= value($)   /*the node name  and  its current peg #.*/
             if nL==fn | nH==fn  then return 1  /*if ≡ ±1,  then the node can't be used.*/
             end   /*ch*/                       /* [↑]  looking for suitable number.    */
   return 0                                     /*the subroutine arg value passed is OK.*/


object NoConnection extends App {

  private def links = Seq(
    Seq(2, 3, 4), // A to C,D,E
    Seq(3, 4, 5), // B to D,E,F
    Seq(2, 4), // D to C, E
    Seq(5), // E to F
    Seq(2, 3, 4), // G to C,D,E
    Seq(3, 4, 5)) // H to D,E,F

  private def genRandom: LazyList[Seq[Int]] = util.Random.shuffle((1 to 8).toList) #:: genRandom

  private def notSolved(links: Seq[Seq[Int]], pegs: Seq[Int]): Boolean =
    links.indices.forall(
      i => !links(i).forall(peg => math.abs(pegs(i) - peg) == 1))

  private def printResult(pegs: Seq[Int]) = {
    println(f"${pegs(0)}%3d${pegs(1)}%2d")
    println(f"${pegs(2)}%1d${pegs(3)}%2d${pegs(4)}%2d${pegs(5)}%2d")
    println(f"${pegs(6)}%3d${pegs(7)}%2d")
  }

  printResult(genRandom.dropWhile(!notSolved(links, _)).head)
}


package require Tcl 8.6
package require struct::list

proc haveAdjacent {a b c d e f g h} {
    expr {
	[edge $a $c] ||
	[edge $a $d] ||
	[edge $a $e] ||
	[edge $b $d] ||
	[edge $b $e] ||
	[edge $b $f] ||
	[edge $c $d] ||
	[edge $c $g] ||
	[edge $d $e] ||
	[edge $d $g] ||
	[edge $d $h] ||
	[edge $e $f] ||
	[edge $e $g] ||
	[edge $e $h] ||
	[edge $f $h]
    }
}
proc edge {x y} {
    expr {abs($x-$y) == 1}
}

set layout [string trim {
        A   B
       /|\ /|\
      / | X | \
     /  |/ \|  \
    C - D - E - F
     \  |\ /|  /
      \ | X | /
       \|/ \|/
        G   H
} \n]
struct::list foreachperm p {1 2 3 4 5 6 7 8} {
    if {![haveAdjacent {*}$p]} {
	puts [string map [join [
	    lmap name {A B C D E F G H} val $p {list $name $val}
	]] $layout]
	break
    }
}


import "/dynamic" for Tuple

var Solution = Tuple.create("Solution", ["p", "tests", "swaps"])

// Holes A=0, B=1, …, H=7
// With connections:
var conn = "
       A   B
      /|\\ /|\\
     / | X | \\
    /  |/ \\|  \\
   C - D - E - F
    \\  |\\ /|  /
     \\ | X | /
      \\|/ \\|/
       G   H
"

var connections = [
	[0, 2], [0, 3], [0, 4], // A to C, D, E
	[1, 3], [1, 4], [1, 5], // B to D, E, F
	[6, 2], [6, 3], [6, 4], // G to C, D, E
	[7, 3], [7, 4], [7, 5], // H to D, E, F
	[2, 3], [3, 4], [4, 5]  // C-D, D-E, E-F
]

// 'isValid' checks if the pegs are a valid solution.
// If the absolute difference between any pair of connected pegs is
// greater than one it is a valid solution.
var isValid = Fn.new { |pegs|
   for (c in connections) {
       if ((pegs[c[0]] - pegs[c[1]]).abs <= 1) return false
   }
   return true
}

var swap = Fn.new { |pegs, i, j|
    var tmp = pegs[i]
    pegs[i] = pegs[j]
    pegs[j] = tmp
}

// 'solve' is a simple recursive brute force solver,
// it stops at the first found solution.
// It returns the solution, the number of positions tested,
// and the number of pegs swapped.
var solve
solve = Fn.new {
    var pegs = List.filled(8, 0)
    for (i in 0..7) pegs[i] = i + 1
    var tests = 0
    var swaps = 0

    var recurse // recursive closure
    recurse = Fn.new { |i|
        if (i >= pegs.count - 1) {
            tests = tests + 1
            return isValid.call(pegs)
        }
        // Try each remaining peg from pegs[i] onwards
        for (j in i...pegs.count) {
            swaps = swaps + 1
            swap.call(pegs, i, j)
            if (recurse.call(i + 1)) return true
            swap.call(pegs, i, j)
        }
        return false
    }

    recurse.call(0)
    return Solution.new(pegs, tests, swaps)
}

var pegsAsString = Fn.new { |pegs|
    var ca = conn.toList
    var i = 0
    for (c in ca) {
        if ("ABCDEFGH".contains(c)) ca[i] = String.fromByte(48 + pegs[c.bytes[0] - 65])
        i = i + 1
    }
    return ca.join()
}

var s = solve.call()
System.print(pegsAsString.call(s.p))
System.print("Tested %(s.tests) positions and did %(s.swaps) swaps.")


include c:\cxpl\codes;

int     Hole, Max, I;
char    Box(8), Str;
def     A, B, C, D, E, F, G, H;
[for Hole:= 0 to 7 do Box(Hole):= Hole+1;
Max:= 7;
while   abs(Box(D)-Box(A)) < 2  or  abs(Box(D)-Box(C)) < 2  or
        abs(Box(D)-Box(G)) < 2  or  abs(Box(D)-Box(E)) < 2  or
        abs(Box(A)-Box(C)) < 2  or  abs(Box(C)-Box(G)) < 2  or
        abs(Box(G)-Box(E)) < 2  or  abs(Box(E)-Box(A)) < 2  or
        abs(Box(E)-Box(B)) < 2  or  abs(Box(E)-Box(H)) < 2  or
        abs(Box(E)-Box(F)) < 2  or  abs(Box(B)-Box(D)) < 2  or
        abs(Box(D)-Box(H)) < 2  or  abs(Box(H)-Box(F)) < 2  or
        abs(Box(F)-Box(B)) < 2  do
           loop [I:= Box(0);                    \next permutation
                for Hole:= 0 to Max-1 do Box(Hole):= Box(Hole+1);
                Box(Max):= I;
                if I # Max+1 then [Max:= 7;  quit]
                else Max:= Max-1];
Str:= "
    #   #
   /|\ /|\
  / | X | \
 /  |/ \|  \
# - # - # - #
 \  |\ /|  /
  \ | X | /
   \|/ \|/
    #   #
";
Hole:= 0;  I:= 0;
repeat  if Str(I)=^# then [Str(I):= Box(Hole)+^0;  Hole:= Hole+1];
        I:= I+1;
until   Hole = 8;
Text(0, Str);
]


const PegA=0, PegB=1, PegC=2, PegD=3, PegE=4, PegF=5, PegG=6, PegH=7;
connections:=T(
   T(PegA, PegC), T(PegA, PegD), T(PegA, PegE),
   T(PegB, PegD), T(PegB, PegE), T(PegB, PegF),
   T(PegC, PegD), T(PegD, PegE), T(PegE, PegF),
   T(PegG, PegC), T(PegG, PegD), T(PegG, PegE),
   T(PegH, PegD), T(PegH, PegE), T(PegH, PegF) );
CZ:=connections.len();
#<<<   // Use "raw" string in a "here doc" so \ isn't a quote char
board:=
0'$        A   B
       /|\ /|\
      / | X | \
     /  |/ \|  \
    C - D - E - F
     \  |\ /|  /
      \ | X | /
       \|/ \|/
        G   H$;
#<<<	// end "here doc"

perm:=T(PegA,PegB,PegC,PegD,PegE,PegF,PegG,PegH); // Peg[8]
foreach p in (Utils.Helpers.permuteW(perm)){ // permutation iterator
   if(connections.filter1('wrap([(a,b)]){ (p[a] - p[b]).abs()<=1 })) continue;
   board.translate("ABCDEFGH",p.apply('+(1)).concat()).println();
   break;  // comment out to see all 16 solutions
}


import mx.rpc.soap.WebService;
import mx.rpc.events.ResultEvent;
var ws:WebService = new WebService();
ws.wsdl = 'http://example.com/soap/wsdl';
ws.soapFunc.addEventListener("result",soapFunc_Result);
ws.anotherSoapFunc.addEventListener("result",anotherSoapFunc_Result);
ws.loadWSDL();
ws.soapFunc();
ws.anotherSoapFunc();
//  method invocation callback handlers
private function soapFunc_Result(event:ResultEvent):void {
  // do something
}
private function anotherSoapFunc_Result(event:ResultEvent):void {
  // do another something
}


WS_Initialize()
    WS_Exec("Set client = CreateObject(""MSSOAP.SoapClient"")")
    WS_Exec("client.MSSoapInit ""http://example.com/soap/wsdl""")
    callhello = client.soapFunc("hello")
    callanother = client.anotherSoapFunc(34234)

    WS_Eval(result, callhello)
    WS_Eval(result2, callanother)
    Msgbox % result . "`n" . result2
    WS_Uninitialize()
#Include ws4ahk.ahk  ; http://www.autohotkey.net/~easycom/ws4ahk_public_api.html


#include <curl/curl.h>
#include <string.h>
#include <stdio.h>

size_t write_data(void *ptr, size_t size, size_t nmeb, void *stream){
    return fwrite(ptr,size,nmeb,stream);
}

size_t read_data(void *ptr, size_t size, size_t nmeb, void *stream){
    return fread(ptr,size,nmeb,stream);
}

void callSOAP(char* URL, char * inFile, char * outFile) {

    FILE * rfp = fopen(inFile, "r");
    if(!rfp)
        perror("Read File Open:");

    FILE * wfp = fopen(outFile, "w+");
    if(!wfp)
        perror("Write File Open:");

    struct curl_slist *header = NULL;
		header = curl_slist_append (header, "Content-Type:text/xml");
		header = curl_slist_append (header, "SOAPAction: rsc");
		header = curl_slist_append (header, "Transfer-Encoding: chunked");
		header = curl_slist_append (header, "Expect:");
    CURL *curl;

    curl = curl_easy_init();
    if(curl) {
        curl_easy_setopt(curl, CURLOPT_URL, URL);
        curl_easy_setopt(curl, CURLOPT_POST, 1L);
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_data);
        curl_easy_setopt(curl, CURLOPT_READDATA, rfp);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, wfp);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)-1);
        curl_easy_setopt(curl, CURLOPT_VERBOSE,1L);
        curl_easy_perform(curl);

        curl_easy_cleanup(curl);
    }
}

int main(int argC,char* argV[])
{
	if(argC!=4)
		printf("Usage : %s <URL of WSDL> <Input file path> <Output File Path>",argV[0]);
	else
		callSOAP(argV[1],argV[2],argV[3]);
	return 0;
}


(require '[clj-soap.core :as soap])

(let [client (soap/client-fn "http://example.com/soap/wsdl")]
  (client :soapFunc)
  (client :anotherSoapFunc))


<cfset client = createObject("webservice","http://example.com/soap/wsdl")>
<cfset result = client.soapFunc("hello")>
<cfset result = client.anotherSoapFunc(34234)>


apt_knowledge(webservices);      // Commanding apt_protocol(SOAP); will also apt_knowledge(webservices);

set_namespace(rosettacode);

add_webserv(ws)_protocol(SOAP)_wdsl(http://example.com/soap/wsdl)_me();
invoke_webserv(ws)_soapFunc(hello)_msg()_result()_me();
me_msg()_invoke(ws)_anotherSoapFunc(32234);                 // alternative syntax

reset_namespace();


open Microsoft.FSharp.Data.TypeProviders

type Wsdl = WsdlService<"http://example.com/soap/wsdl">
let result = Wsdl.soapFunc("hello")
let result2 = Wsdl.anotherSoapFunc(34234)


package main

import (
    "fmt"
    "github.com/tiaguinho/gosoap"
    "log"
)

type CheckVatResponse struct {
    CountryCode string `xml:"countryCode"`
    VatNumber   string `xml:"vatNumber"`
    RequestDate string `xml:"requestDate"`
    Valid       string `xml:"valid"`
    Name        string `xml:"name"`
    Address     string `xml:"address"`
}

var (
    rv CheckVatResponse
)

func check(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

func main() {
    // create SOAP client
    soap, err := gosoap.SoapClient("http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl")

    // map parameter names to values
    params := gosoap.Params{
        "vatNumber":   "6388047V",
        "countryCode": "IE",
    }

    // call 'checkVat' function
    err = soap.Call("checkVat", params)
    check(err)

    // unmarshal response to 'rv'
    err = soap.Unmarshal(&rv)
    check(err)

    // print response
    fmt.Println("Country Code  : ", rv.CountryCode)
    fmt.Println("Vat Number    : ", rv.VatNumber)
    fmt.Println("Request Date  : ", rv.RequestDate)
    fmt.Println("Valid         : ", rv.Valid)
    fmt.Println("Name          : ", rv.Name)
    fmt.Println("Address       : ", rv.Address)
}


import soap

procedure main(A)
    soap := SoapClient(A[1] | "http://example.com/soap/wsdl")  # Allow override of default
    write("soapFunc: ",soap.call("soapFunc"))
    write("anotherSoapFunc: ",soap.call("anotherSoapFunc"))
end


using LibCURL

function callSOAP(url, infilename, outfilename)
    rfp = open(infilename, "r")
    wfp = open(outfilename, "w+")

    header = curl_slist_append(header, "Content-Type:text/xml")
    header = curl_slist_append(header, "SOAPAction: rsc");
    header = curl_slist_append(header, "Transfer-Encoding: chunked")
    header = curl_slist_append(header, "Expect:")

    curl = curl_easy_init();
    curl_easy_setopt(curl, CURLOPT_URL, URL)
    curl_easy_setopt(curl, CURLOPT_POST, 1L)
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_data)
    curl_easy_setopt(curl, CURLOPT_READDATA, rfp)
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data)
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, wfp)
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header)
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)-1)
    curl_easy_setopt(curl, CURLOPT_VERBOSE,1L)
    curl_easy_perform(curl)

    curl_easy_cleanup(curl)
end

try
    callSOAP(ARGS[1], ARGS[2], ARGS[3])
catch y
    println("Usage : $(@__FILE__) <URL of WSDL> <Input file path> <Output File Path>")
end


// libcurl.def
headers = /usr/include/curl/curl.h
linkerOpts.linux = -L/usr/lib/x86_64-linux-gnu -lcurl


use SOAP::Lite;

print SOAP::Lite
  -> service('http://example.com/soap/wsdl')
  -> soapFunc("hello");
print SOAP::Lite
  -> service('http://example.com/soap/wsdl')
  -> anotherSoapFunc(34234);


--
-- demo\rosetta\SOAP.exw
-- =====================
--
-- translated from https://gist.github.com/p120ph37/8281362ae9da042f3043
--
without js -- (libcurl)
include builtins\libcurl.e
include builtins\xml.e      -- xml_encode()

function write_callback(atom pData, integer size, nmemb, atom /*pUserdata*/)
    integer bytes_written = size*nmemb
    puts(1,peek({pData,bytes_written}))
    return bytes_written
end function
constant write_cb = call_back({'+',write_callback})

function compose_soap_frobnicate(string foo, bar, baz)
  return sprintf("""
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Body>
  <frobnicate xmlns="http://example.com/frobnicate">
   <foo>%s</foo>
   <bar>%s</bar>
   <baz>%s</baz>
  </frobnicate>
 </soap:Body>
</soap:Envelope>""",{xml_encode(foo),xml_encode(bar),xml_encode(baz)})
end function

curl_global_init()
atom curl = curl_easy_init()
curl_easy_setopt(curl, CURLOPT_URL, "https://ameriwether.com/cgi-bin/info.pl")
string soap = compose_soap_frobnicate("'Ein'", ">Zwei<", "\"Drei\"")
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, soap)
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC)
curl_easy_setopt(curl, CURLOPT_USERNAME, "user")
curl_easy_setopt(curl, CURLOPT_PASSWORD, "password")
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb)
atom headers = NULL
headers = curl_slist_append(headers, "Content-Type: text/xml; charset=utf-8")
headers = curl_slist_append(headers, "SOAPAction: \"https://ameriwether.com/cgi-bin/info.pl/frobnicate\"")
headers = curl_slist_append(headers, "Accept: text/plain") -- Example output easier to read as plain text.
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers)
-- Make the example URL work even if your CA bundle is missing.
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false)
CURLcode res = curl_easy_perform(curl)
if res!=CURLE_OK then
    printf(2, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res))
end if
curl_slist_free_all(headers)
curl_easy_cleanup(curl)
curl_global_cleanup()


<?php
//load the wsdl file
$client = new SoapClient("http://example.com/soap/definition.wsdl");
//functions are now available to be called
$result = $client->soapFunc("hello");
$result = $client->anotherSoapFunc(34234);

//SOAP Information
$client = new SoapClient("http://example.com/soap/definition.wsdl");
//list of SOAP types
print_r($client->__getTypes());
//list if SOAP Functions
print_r($client->__getFunctions());
?>


XIncludeFile "COMatePLUS.pbi"
Define.COMateObject soapObject = COMate_CreateObject("MSSOAP.SoapClient")
soapObject\Invoke("MSSoapInit('http://example.com/soap/wsdl')")
result = soapObject\Invoke("soapFunc('hello')")
result2 = soapObject\Invoke("anotherSoapFunc(34234)")


from SOAPpy import WSDL
proxy = WSDL.Proxy("http://example.com/soap/wsdl")
result = proxy.soapFunc("hello")
result = proxy.anotherSoapFunc(34234)


# Reference:
# https://github.com/retupmoca/P6-SOAP
# http://wiki.dreamfactory.com/DreamFactory/Tutorials/Temp_Conversion_SOAP_API

use v6;
use SOAP::Client;

my $request = SOAP::Client.new('http://www.w3schools.com/xml/tempconvert.asmx?WSDL') or die;

say $request.call('CelsiusToFahrenheit', Celsius => 100 ) or die;

say $request.call('FahrenheitToCelsius', Fahrenheit => 212 ) or die;


require 'soap/wsdlDriver'

wsdl = SOAP::WSDLDriverFactory.new("http://example.com/soap/wsdl")
soap = wsdl.create_rpc_driver

response1 = soap.soapFunc(:elementName => "value")
puts response1.soapFuncReturn

response2 = soap.anotherSoapFunc(:aNumber => 42)
puts response2.anotherSoapFuncReturn


| service client response1 response2 |

service := SprayWSDLService onUrl: 'http://example.com/soap/wsdl'.

client := service createClient.
response1 := client send: 'soapFunc' withArguments:{ 'hello' }.
response2 := client send: 'anotherSoapFunc' withArguments:{ 34234 }.


package require WS::Client

# Grok the service, and generate stubs
::WS::Client::GetAndParseWsdl http://example.com/soap/wsdl
::WS::Client::CreateStubs ExampleService   ;# Assume that's the service name...

# Do the calls
set result1 [ExampleService::soapFunc "hello"]
set result2 [ExampleService::anotherSoapFunc 34234]


variables
   string result1, result2
endvariables

activate "webservice".soapFunc("hello", result1)
activate "webservice".anotherSoapFunc(34234, result2)


Dim client
Dim result
Set client = CreateObject("MSSOAP.SoapClient")
client.MSSoapInit "http://example.com/soap/wsdl"
result = client.soapFunc("hello")
result = client.anotherSoapFunc(34234)


LOCAL oSoapClient 	AS OBJECT //OLEAUTOOBJECT
LOCAL cUrl 		AS STRING
LOCAL uResult        AS USUAL
oSoapClient := OLEAutoObject{"MSSOAP.SoapClient30"}
cUrl        := "http://example.com/soap/wsdl"
IF oSoapClient:fInit
   oSoapClient:mssoapinit(cUrl,"", "", "" )
   uResult := oSoapClient:soapFunc("hello")
   uResult := oSoapClient:anotherSoapFunc(34234)
ENDIF


/* soap.wren */

var CURLOPT_URL = 10002
var CURLOPT_POST = 47
var CURLOPT_READFUNCTION = 20012
var CURLOPT_READDATA = 10009
var CURLOPT_WRITEFUNCTION = 20011
var CURLOPT_WRITEDATA = 10001
var CURLOPT_HTTPHEADER = 10023
var CURLOPT_POSTFIELDSIZE_LARGE = 30120
var CURLOPT_VERBOSE = 41

foreign class File {
    foreign static url

    foreign static readFile

    foreign static writeFile

    construct open(filename, mode) {}
}

foreign class CurlSlist {
    construct new() {}

    foreign append(s)
}

foreign class Curl {
    construct easyInit() {}

    foreign easySetOpt(opt, param)

    foreign easyPerform()

    foreign easyCleanup()
}

var soap = Fn.new { |url, inFile, outFile|
    var rfp = File.open(inFile, "r")
    if (rfp == 0) Fiber.abort("Error opening read file.")
    var wfp = File.open(outFile, "w+")
    if (wfp == 0) Fiber.abort("Error opening write file.")

    var header = CurlSlist.new()
    header = header.append("Content-Type:text/xml")
    header = header.append("SOAPAction: rsc")
    header = header.append("Transfer-Encoding: chunked")
    header = header.append("Expect:")

    var curl = Curl.easyInit()
    if (curl == 0) Fiber.abort("Error initializing cURL.")
    curl.easySetOpt(CURLOPT_URL, url)
    curl.easySetOpt(CURLOPT_POST, 1)
    curl.easySetOpt(CURLOPT_READFUNCTION, 0)  // read function to be supplied by C
    curl.easySetOpt(CURLOPT_READDATA, rfp)
    curl.easySetOpt(CURLOPT_WRITEFUNCTION, 0) // write function to be supplied by C
    curl.easySetOpt(CURLOPT_WRITEDATA, wfp)
    curl.easySetOpt(CURLOPT_HTTPHEADER, header)
    curl.easySetOpt(CURLOPT_POSTFIELDSIZE_LARGE, -1)
    curl.easySetOpt(CURLOPT_VERBOSE, 1)

    curl.easyPerform()
    curl.easyCleanup()
}

soap.call(File.url, File.readFile, File.writeFile)


SolveNumbrix(Grid, Locked, Max, row, col, num:=1, R:="", C:=""){
	if (R&&C)							; if neighbors (not first iteration)
	{
		Grid[R, C] := ">" num 					; place num in current neighbor and mark it visited ">"
		row:=R, col:=C						; move to current neighbor
	}

	num++								; increment num
	if (num=max)							; if reached end
		return map(Grid)					; return solution

	if locked[num]							; if current num is a locked value
	{
		row := StrSplit((StrSplit(locked[num], ",").1) , ":").1	; find row of num
		col := StrSplit((StrSplit(locked[num], ",").1) , ":").2	; find col of num
		if SolveNumbrix(Grid, Locked, Max, row, col, num)	; solve for current location and value
			return map(Grid)				; if solved, return solution
	}
	else
	{
		for each, value in StrSplit(Neighbor(row,col), ",")
		{
			R := StrSplit(value, ":").1
			C := StrSplit(value, ":").2

			if (Grid[R,C] = "")				; a hole or out of bounds
			|| InStr(Grid[R, C], ">")			; visited
			|| Locked[num+1] && !(Locked[num+1]~= "\b" R ":" C "\b") ; not neighbor of locked[num+1]
			|| Locked[num-1] && !(Locked[num-1]~= "\b" R ":" C "\b") ; not neighbor of locked[num-1]
			|| Locked[num]					; locked value
			|| Locked[Grid[R, C]]				; locked cell
				continue

			if SolveNumbrix(Grid, Locked, Max, row, col, num, R, C)	; solve for current location, neighbor and value
				return map(Grid)			; if solved, return solution
		}
	}
	num--								; step back
	for i, line in Grid
		for j, element in line
			if InStr(element, ">") && (StrReplace(element, ">") >= num)
				Grid[i, j] := 0
}
;--------------------------------
;--------------------------------
;--------------------------------
Neighbor(row,col){
	return row-1 ":" col
	. "," row+1 ":" col
	. "," row ":" col+1
	. "," row ":" col-1
}
;--------------------------------
map(Grid){
	for i, row in Grid
	{
		for j, element in row
			line .= (A_Index > 1 ? "`t" : "") . element
		map .= (map<>""?"`n":"") line
		line := ""
	}
	return StrReplace(map, ">")
}


using System.Collections;
using System.Collections.Generic;
using static System.Console;
using static System.Math;
using static System.Linq.Enumerable;

public class Solver
{
    private static readonly (int dx, int dy)[]
        //other puzzle types elided
        numbrixMoves = {(1,0),(0,1),(-1,0),(0,-1)};

    private (int dx, int dy)[] moves;

    public static void Main()
    {
        var numbrixSolver = new Solver(numbrixMoves);
        Print(numbrixSolver.Solve(false, new [,] {
            {  0,  0,  0,  0,  0,  0,  0,  0,  0 },
            {  0,  0, 46, 45,  0, 55, 74,  0,  0 },
            {  0, 38,  0,  0, 43,  0,  0, 78,  0 },
            {  0, 35,  0,  0,  0,  0,  0, 71,  0 },
            {  0,  0, 33,  0,  0,  0, 59,  0,  0 },
            {  0, 17,  0,  0,  0,  0,  0, 67,  0 },
            {  0, 18,  0,  0, 11,  0,  0, 64,  0 },
            {  0,  0, 24, 21,  0,  1,  2,  0,  0 },
            {  0,  0,  0,  0,  0,  0,  0,  0,  0 },
        }));

        Print(numbrixSolver.Solve(false, new [,] {
            {  0,  0,  0,  0,  0,  0,  0,  0,  0 },
            {  0, 11, 12, 15, 18, 21, 62, 61,  0 },
            {  0,  6,  0,  0,  0,  0,  0, 60,  0 },
            {  0, 33,  0,  0,  0,  0,  0, 57,  0 },
            {  0, 32,  0,  0,  0,  0,  0, 56,  0 },
            {  0, 37,  0,  1,  0,  0,  0, 73,  0 },
            {  0, 38,  0,  0,  0,  0,  0, 72,  0 },
            {  0, 43, 44, 47, 48, 51, 76, 77,  0 },
            {  0,  0,  0,  0,  0,  0,  0,  0,  0 },
        }));
    }

    public Solver(params (int dx, int dy)[] moves) => this.moves = moves;

    public int[,] Solve(bool circular, params string[] puzzle)
    {
        var (board, given, count) = Parse(puzzle);
        return Solve(board, given, count, circular);
    }

    public int[,] Solve(bool circular, int[,] puzzle)
    {
        var (board, given, count) = Parse(puzzle);
        return Solve(board, given, count, circular);
    }

    private int[,] Solve(int[,] board, BitArray given, int count, bool circular)
    {
        var (height, width) = (board.GetLength(0), board.GetLength(1));
        bool solved = false;
        for (int x = 0; x < height && !solved; x++) {
            solved = Range(0, width).Any(y => Solve(board, given, circular, (height, width), (x, y), count, (x, y), 1));
            if (solved) return board;
        }
        return null;
    }

    private bool Solve(int[,] board, BitArray given, bool circular,
        (int h, int w) size, (int x, int y) start, int last, (int x, int y) current, int n)
    {
        var (x, y) = current;
        if (x < 0 || x >= size.h || y < 0 || y >= size.w) return false;
        if (board[x, y] < 0) return false;
        if (given[n - 1]) {
            if (board[x, y] != n) return false;
        } else if (board[x, y] > 0) return false;
        board[x, y] = n;
        if (n == last) {
            if (!circular || AreNeighbors(start, current)) return true;
        }
        for (int i = 0; i < moves.Length; i++) {
            var move = moves[i];
            if (Solve(board, given, circular, size, start, last, (x + move.dx, y + move.dy), n + 1)) return true;
        }
        if (!given[n - 1]) board[x, y] = 0;
        return false;

        bool AreNeighbors((int x, int y) p1, (int x, int y) p2) => moves.Any(m => (p2.x + m.dx, p2.y + m.dy).Equals(p1));
    }

    private static (int[,] board, BitArray given, int count) Parse(string[] input)
    {
        (int height, int width) = (input.Length, input[0].Length);
        int[,] board = new int[height, width];
        int count = 0;
        for (int x = 0; x < height; x++) {
            string line = input[x];
            for (int y = 0; y < width; y++) {
                board[x, y] = y < line.Length && char.IsDigit(line[y]) ? line[y] - '0' : -1;
                if (board[x, y] >= 0) count++;
            }
        }
        BitArray given = Scan(board, count, height, width);
        return (board, given, count);
    }

    private static (int[,] board, BitArray given, int count) Parse(int[,] input)
    {
        (int height, int width) = (input.GetLength(0), input.GetLength(1));
        int[,] board = new int[height, width];
        int count = 0;
        for (int x = 0; x < height; x++)
            for (int y = 0; y < width; y++)
                if ((board[x, y] = input[x, y]) >= 0) count++;
        BitArray given = Scan(board, count, height, width);
        return (board, given, count);
    }

    private static BitArray Scan(int[,] board, int count, int height, int width)
    {
        var given = new BitArray(count + 1);
        for (int x = 0; x < height; x++)
            for (int y = 0; y < width; y++)
                if (board[x, y] > 0) given[board[x, y] - 1] = true;
        return given;
    }

    private static void Print(int[,] board)
    {
        if (board == null) {
            WriteLine("No solution");
        } else {
            int w = board.Cast<int>().Where(i => i > 0).Max(i => (int?)Ceiling(Log10(i+1))) ?? 1;
            string e = new string('-', w);
            foreach (int x in Range(0, board.GetLength(0)))
                WriteLine(string.Join(" ", Range(0, board.GetLength(1))
                    .Select(y => board[x, y] < 0 ? e : board[x, y].ToString().PadLeft(w, ' '))));
        }
        WriteLine();
    }

}


#include <vector>
#include <sstream>
#include <iostream>
#include <iterator>
#include <cstdlib>
#include <string>
#include <bitset>

using namespace std;
typedef bitset<4> hood_t;

struct node
{
	int val;
	hood_t neighbors;
};

class nSolver
{
public:

	void solve(vector<string>& puzz, int max_wid)
	{
		if (puzz.size() < 1) return;
		wid = max_wid;
		hei = static_cast<int>(puzz.size()) / wid;
		max = wid * hei;
		int len = max, c = 0;
		arr = vector<node>(len, node({ 0, 0 }));
		weHave = vector<bool>(len + 1, false);

		for (const auto& s : puzz)
		{
			if (s == "*") { max--; arr[c++].val = -1; continue; }
			arr[c].val = atoi(s.c_str());
			if (arr[c].val > 0) weHave[arr[c].val] = true;
			c++;
		}

		solveIt(); c = 0;
		for (auto&& s : puzz)
		{
			if (s == ".")
				s = std::to_string(arr[c].val);
			c++;
		}
	}

private:
	bool search(int x, int y, int w, int dr)
	{
		if ((w > max && dr > 0) || (w < 1 && dr < 0) || (w == max && weHave[w])) return true;

		node& n = arr[x + y * wid];
		n.neighbors = getNeighbors(x, y);
		if (weHave[w])
		{
			for (int d = 0; d < 4; d++)
			{
				if (n.neighbors[d])
				{
					int a = x + dx[d], b = y + dy[d];
					if (arr[a + b * wid].val == w)
						if (search(a, b, w + dr, dr))
							return true;
				}
			}
			return false;
		}

		for (int d = 0; d < 4; d++)
		{
			if (n.neighbors[d])
			{
				int a = x + dx[d], b = y + dy[d];
				if (arr[a + b * wid].val == 0)
				{
					arr[a + b * wid].val = w;
					if (search(a, b, w + dr, dr))
						return true;
					arr[a + b * wid].val = 0;
				}
			}
		}
		return false;
	}

	hood_t getNeighbors(int x, int y)
	{
		hood_t retval;
		for (int xx = 0; xx < 4; xx++)
		{
			int a = x + dx[xx], b = y + dy[xx];
			if (a < 0 || b < 0 || a >= wid || b >= hei)
				continue;
			if (arr[a + b * wid].val > -1)
				retval.set(xx);
		}
		return retval;
	}

	void solveIt()
	{
		int x, y, z; findStart(x, y, z);
		if (z == 99999) { cout << "\nCan't find start point!\n"; return; }
		search(x, y, z + 1, 1);
		if (z > 1) search(x, y, z - 1, -1);
	}

	void findStart(int& x, int& y, int& z)
	{
		z = 99999;
		for (int b = 0; b < hei; b++)
		for (int a = 0; a < wid; a++)
		if (arr[a + wid * b].val > 0 && arr[a + wid * b].val < z)
		{
			x = a; y = b;
			z = arr[a + wid * b].val;
		}

	}

	vector<int> dx = vector<int>({ -1, 1, 0, 0 });
	vector<int> dy = vector<int>({ 0, 0, -1, 1 });
	int wid, hei, max;
	vector<node> arr;
	vector<bool> weHave;
};

//------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
	int wid; string p;
	//p = ". . . . . . . . . . . 46 45 . 55 74 . . . 38 . . 43 . . 78 . . 35 . . . . . 71 . . . 33 . . . 59 . . . 17 . . . . . 67 . . 18 . . 11 . . 64 . . . 24 21 . 1  2 . . . . . . . . . . ."; wid = 9;
	//p = ". . . . . . . . . . 11 12 15 18 21 62 61 . .  6 . . . . . 60 . . 33 . . . . . 57 . . 32 . . . . . 56 . . 37 .  1 . . . 73 . . 38 . . . . . 72 . . 43 44 47 48 51 76 77 . . . . . . . . . ."; wid = 9;
	p = "17 . . . 11 . . . 59 . 15 . . 6 . . 61 . . . 3 . . .  63 . . . . . . 66 . . . . 23 24 . 68 67 78 . 54 55 . . . . 72 . . . . . . 35 . . . 49 . . . 29 . . 40 . . 47 . 31 . . . 39 . . . 45"; wid = 9;

	istringstream iss(p); vector<string> puzz;
	copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter<vector<string> >(puzz));
	nSolver s; s.solve(puzz, wid);

	int c = 0;
	for (const auto& s : puzz)
	{
		if (s != "*" && s != ".")
		{
			if (atoi(s.c_str()) < 10) cout << "0";
			cout << s << " ";
		}
		else cout << "   ";
		if (++c >= wid) { cout << endl; c = 0; }
	}
	cout << endl << endl;
	return system("pause");
}


import std.stdio, std.conv, std.string, std.range, std.array, std.typecons, std.algorithm;

struct  {
    alias BitSet8 = ubyte; // A set of 8 bits.
    alias Cell = uint;
    enum : string { unavailableInCell = "#", availableInCell = "." }
    enum : Cell { unavailableCell = Cell.max, availableCell = 0 }

    this(in string inPuzzle) pure @safe {
        const rawPuzzle = inPuzzle.splitLines.map!(row => row.split).array;
        assert(!rawPuzzle.empty);
        assert(!rawPuzzle[0].empty);
        assert(rawPuzzle.all!(row => row.length == rawPuzzle[0].length)); // Is rectangular.

        gridWidth = rawPuzzle[0].length;
        gridHeight = rawPuzzle.length;
        immutable nMaxCells = gridWidth * gridHeight;
        grid = new Cell[nMaxCells];
        auto knownMutable = new bool[nMaxCells + 1];
        uint nAvailableMutable = nMaxCells;
        bool[Cell] seenCells; // To avoid duplicate input numbers.

        uint i = 0;
        foreach (const piece; rawPuzzle.join) {
            if (piece == unavailableInCell) {
                nAvailableMutable--;
                grid[i++] = unavailableCell;
                continue;
            } else if (piece == availableInCell) {
                grid[i] = availableCell;
            } else {
                immutable cell = piece.to!Cell;
                assert(cell > 0 && cell <= nMaxCells);
                assert(cell !in seenCells);
                seenCells[cell] = true;
                knownMutable[cell] = true;
                grid[i] = cell;
            }

            i++;
        }

        known = knownMutable.idup;
        nAvailable = nAvailableMutable;
    }

    @disable this();

    auto solve() pure nothrow @safe @nogc
    out(result) {
        if (!result.isNull) {
            // Can't verify 'result' here because it's const.
            // assert(!result.get.join.canFind(availableCell.text));

            assert(!grid.canFind(availableCell));
            auto values = grid.filter!(c => c != unavailableCell);
            auto interval = iota(reduce!min(values.front, values.dropOne),
                                 reduce!max(values.front, values.dropOne) + 1);
            assert(values.walkLength == interval.length);
            assert(interval.all!(c => values.count(c) == 1)); // Quadratic.
        }
    } body {
        auto result = grid
                      .map!(c => (c == unavailableCell) ? unavailableInCell : c.text)
                      .chunks(gridWidth);
        alias OutRange = Nullable!(typeof(result));

        const start = findStart;
        if (start.isNull)
            return OutRange();

        search(start.r, start.c, start.cell + 1, 1);
        if (start.cell > 1) {
            immutable direction = -1;
            search(start.r, start.c, start.cell + direction, direction);
        }

        if (grid.any!(c => c == availableCell))
            return OutRange();
        else
            return OutRange(result);
    }

    private:

    bool search(in uint r, in uint c, in Cell cell, in int direction)
    pure nothrow @safe @nogc {
        if ((cell > nAvailable && direction > 0) || (cell == 0 && direction < 0) ||
            (cell == nAvailable && known[cell]))
            return true; // One solution found.

        immutable neighbors = getNeighbors(r, c);

        if (known[cell]) {
            foreach (immutable i, immutable rc; shifts) {
                if (neighbors & (1u << i)) {
                    immutable c2 = c + rc[0],
                              r2 = r + rc[1];
                    if (grid[r2 * gridWidth + c2] == cell)
                        if (search(r2, c2, cell + direction, direction))
                            return true;
                }
            }
            return false;
        }

        foreach (immutable i, immutable rc; shifts) {
            if (neighbors & (1u << i)) {
                immutable c2 = c + rc[0],
                          r2 = r + rc[1],
                          pos = r2 * gridWidth + c2;
                if (grid[pos] == availableCell) {
                    grid[pos] = cell;          // Try.
                    if (search(r2, c2, cell + direction, direction))
                        return true;
                    grid[pos] = availableCell; // Restore.
                }
            }
        }
        return false;
    }

    BitSet8 getNeighbors(in uint r, in uint c) const pure nothrow @safe @nogc {
        typeof(return) usable = 0;

        foreach (immutable i, immutable rc; shifts) {
            immutable c2 = c + rc[0],
                      r2 = r + rc[1];
            if (c2 >= gridWidth || r2 >= gridHeight)
                continue;
            if (grid[r2 * gridWidth + c2] != unavailableCell)
                usable |= (1u << i);
        }

        return usable;
    }

    auto findStart() const pure nothrow @safe @nogc {
        alias Triple = Tuple!(uint,"r", uint,"c", Cell,"cell");
        Nullable!Triple result;

        auto cell = Cell.max;
        foreach (immutable r; 0 .. gridHeight) {
            foreach (immutable c; 0 .. gridWidth) {
                immutable pos = gridWidth * r + c;
                if (grid[pos] != availableCell &&
                    grid[pos] != unavailableCell && grid[pos] < cell) {
                    cell = grid[pos];
                    result = Triple(r, c, cell);
                }
            }
        }

        return result;
    }

    static immutable int[2][4] shifts = [[0, -1], [0, 1], [-1, 0], [1, 0]];
    immutable uint gridWidth, gridHeight;
    immutable int nAvailable;
    immutable bool[] known; // Given known cells of the puzzle.
    Cell[] grid;  // Flattened mutable game grid.
}

void main() {
    // enum NumbrixPuzzle to catch malformed puzzles at compile-time.
    enum puzzle1 = ".  .  .  .  .  .  .  .  .
                    .  . 46 45  . 55 74  .  .
                    . 38  .  . 43  .  . 78  .
                    . 35  .  .  .  .  . 71  .
                    .  . 33  .  .  . 59  .  .
                    . 17  .  .  .  .  . 67  .
                    . 18  .  . 11  .  . 64  .
                    .  . 24 21  .  1  2  .  .
                    .  .  .  .  .  .  .  .  .".NumbrixPuzzle;

    enum puzzle2 = ".  .  .  .  .  .  .  .  .
                    . 11 12 15 18 21 62 61  .
                    .  6  .  .  .  .  . 60  .
                    . 33  .  .  .  .  . 57  .
                    . 32  .  .  .  .  . 56  .
                    . 37  .  1  .  .  . 73  .
                    . 38  .  .  .  .  . 72  .
                    . 43 44 47 48 51 76 77  .
                    .  .  .  .  .  .  .  .  .".NumbrixPuzzle;

    enum puzzle3 = "17  .  .  . 11  .  .  . 59
                     . 15  .  .  6  .  . 61  .
                     .  .  3  .  .  . 63  .  .
                     .  .  .  . 66  .  .  .  .
                    23 24  . 68 67 78  . 54 55
                     .  .  .  . 72  .  .  .  .
                     .  . 35  .  .  . 49  .  .
                     . 29  .  . 40  .  . 47  .
                    31  .  .  . 39  .  .  . 45".NumbrixPuzzle;

    foreach (puzzle; [puzzle1, puzzle2, puzzle3]) {
        auto solution = puzzle.solve; // Solved at run-time.
        if (solution.isNull)
            writeln("No solution found for puzzle.\n");
        else
            writefln("One solution:\n%(%-(%2s %)\n%)\n", solution);
    }
}