title: Smallest chess program

text:
# Question
Title: Smallest chess program
Inspired by this recent article telling of a French programmer who wrote a 487 byte 2-player (human vs. human) chess program in Assembly, I wondered how small chess programs could be in other languages.

**Details**

* The program must only accept legal chess moves.
* Declaration of check/checkmate is not necessary (just desirable), although the first rule applies in cases of check.
* As per the article, castling is not a necessary implementation.
* Also, you do not have to implement en passant.
* You do however, have to permit pawn promotion upon reaching eighth rank (you may opt to simply force conversion to queen).
* It is up to you how the board is displayed - terminal ASCII, GUI, etc.
* You must display whose turn it is.

The rules of chess can be found here \- ignore specified tournament rules (e.g. timing, touching), and remember castling and en passant are not necessary implementations.

# Answer
> 23 votes
# C, ~~650~~ 600

```
n=8,t=65,s,f,x,y,p,e,u=10,w=32,z=95;char a[95],b[95]="RNBKQBNR";v(){p=a[s]&z;y=f/u-s/u;x=f-s-y*u;e=x*x+y*y;n=s%u/8|f%u/8|a[s]/w-t/w|a[f]/w==t/w|!(p==75&e<3|p>80&x*y==0|p%5==1&x*x==y*y|p==78&e==5|p==80&x*(z-t)>0&(a[f]-w?e==2:e==1|e==4&s%5==1));if(!n&&p-78)for(e=(f-s)/abs(x*x>y*y?x:y),x=s;(x+=e)-f;)n|=a[x]-w;}main(){for(a[93]=40;n--;a[92]=47)sprintf(a,"%s%cP    p%c \n",a,b[n],b[n]+w);for(;1;){puts(a);for(n=1;n;){putchar(t);scanf("%d%d",&s,&f);v();memcpy(b,a,z);if(!n){a[f]=p-80|f%u%7?a[s]:t+16;a[s]=w;a[f]&z^75||(a[z-t/w]=f);f=a[z-t/w];t^=w;for(n=1,s=80;n&&s--;)v();if(n=!n)memcpy(a,b,z),t^=32;}}}}

```

To reduce the code for initializing the board, the display has White (uppercase) playing from left to right and Black (lowercase) playing from right to left. Input is in the form of two 2-digit decimal numbers (start position and finish position), giving file(0-7) and rank(0-7). For a bit of extra code (subtract 11 from each input), input could be made to comply with http://en.wikipedia.org/wiki/ICCF\_numeric\_notation (digits 1-8)

Here's a sample screenshot where Black has just advanced his Rook's Pawn. White tries various illegal moves with his queen, before finally capturing the pawn. Turn indicators are `a` for Black and `A` for White.

An interesting feature of my validation is the use of the square of the Euclidean distance. For the knight this is always 1^2+2^2=5, but I also use it for the King and the pawn.

Test for Check is done by backing up the board, carrying out the players move, and scanning all 64 possible opponent's moves.

The program has to be ended with Ctrl-C. I cant think of a more gracious way of doing it, other than putting in a special move to end the program. A game of chess actually ends when one player is unable to move on his turn (checkmate or stalemate) and that requires a lot of tests that arent required by the spec.

**Commented code**

```
n=8,t=65,s,f,x,y,p,e,u=10,w=32,z=95;                 // 8,10 height and width of board. w=ASCII space, also difference between ucase and lcase
                                                     // 95 is bitmask for conversion lowercase to uppercase, but also used as length of array, etc.
char a[95],b[95]="RNBKQBNR";                         // a is main board, b is backup board (but used at start to hold 1st row data.)

v(){                                                 // validate move in all aspects except check
  p=a[s]&z;                                          // p=uppercase(character on start square)
  y=f/u-s/u;                                         // signed distance in y direction
  x=f-s-y*u;                                         // and x direction
  e=x*x+y*y;                                         // square of Euclidean distance
  n=s%u/8|f%u/8|                                     // n=true if 2nd digit of input out of bounds OR
  a[s]/w-t/w|a[f]/w==t/w|                            // start sq not friendly piece OR finish sq is friendly piece (also eliminates case where start=finish)
  !(                                                 // OR NOT geometry valid
    p==75&e<3|                                       // 'K'(ASCII75) AND euclidean distance squared =1 or 2 OR
    p>80&x*y==0|                                     // 'Q'or'R' AND x or y = 0 OR
    p%5==1&x*x==y*y|                                 // 'Q'or'B' AND abs(x)=abs(y)
    p==78&e==5|                                      // 'N' AND euclidean distance squared = 5
    p==80&x*(z-t)>0&(a[f]-w?e==2:e==1|e==4&s%5==1)   // 'P'(ASCII80):x direction must correspond with case of player (z-t)
  );                                                 // if capturing e=2. Otherwise e=1 (except on start rows 1 and 6, e can be 4)
  if(!n&&p-78)                                       // if not yet invalid and piece not 'N'(ASCII78)
    for(e=(f-s)/abs(x*x>y*y?x:y),x=s;(x+=e)-f;)      // Set e to the numeric difference to travel 1 square in right direction. Set x to start square
       n|=a[x]-w;                                    // and iterate x through all intervening squares, checking they are blank
}

main(){

  for(a[93]=40;n--;a[92]=47)                         // iterate n through 8 rows of board. vacant spaces in bracket are use to assign start positions of kings to a[92&93]
    sprintf(a,"%s%cP    p%c \n",a,b[n],b[n]+w);      // build up start position, each row 10 squares wide, including filler space the end and newline

  for(;1;){                                          // loop forever
    puts(a);                                         // display board
    for(n=1;n;){                                     // loop while move invalid
      putchar(t);                                    // display prompt 'A' for white 'a' for black
      scanf("%d%d",&s,&f);                           // get input
      v();                                           // validate move
      memcpy(b,a,z);                                 // backup board (and king position metadata)
      if(!n){                                        // if move not yet invalid
        a[f]=p-80|f%u%7?a[s]:t+16;                   // if not a pawn on last row, content of finish square = start square, ELSE queen of correct case (t+16)
        a[s]=w;                                      // start square becomes blank (ASCII32)
        a[f]&z^75||(a[z-t/w]=f);                     // if finish square king, update king position metadata
        f=a[z-t/w];                                  // to begin scanning to see if king in check, set f to current king position
        t^=w;                                        // and change colour
        for(n=1,s=80;n&&s--;)v();                    // for s=79..0 search for valid opponent move to capture king (stops with n=0)
        if(n=!n)memcpy(a,b,z),t^=32;                 // valid opponent threat on king means invalid player move. Invert n, recover board from backup and change colour back.
      }
    }
  }
}

```

# Answer
> 13 votes
# Python 3, 1166 1071 993 bytes

I only realized I needed to stop kings from moving into check after I had otherwise finished, but here's my submission anyways

```
h=abs
m=range
l=print
o=" "
a=o*8
j=[list(s)for s in["RNBKQBNR","P"*8,a,a,a,a,"p"*8,"rnbkqbnr"]]
u=False
v=lambda c:(c.lower()==c)==u
while 1:
 l("b"if u else"w")
 for b in j:l(*b)
 q,r,s,t=[int(i)for i in input().split()];P=j[r][q];g=j[t][s];p=P.lower()
 def w():
  if g==o or not v(g):j[t][s]=P;j[r][q]=o;global u;u=not u
 if not v(P):break
 if p=="r"or p=="q":
  for a,b,c,d in[(q,r,s,t),(r,q,t,s)]:
   if a==c:
    x=h(d-b)//(d-b)
    for n in m(b+x,d,x):
     if j[n if b else r][q if b else n]!=o:break
    else:w()
 if p=="b"or p=="q":
  if h(q-s)==h(r-t):
   for n in m(1, h(q-s)):
    if j[r+(n if t>r else-n)][q+(n if s>q else-n)]!=o:break
   else:w()
 if p=="k"and h(q-s)<2 and h(r-t)<2 or(p=="n"and(h(q-s)==2 and h(r-t)==1 or h(r-t)==2 and h(q-s)==1)):w()
 if p=="p":
  f=t-r==(-1 if u else 1)
  if(g!=o and not v(g)and h(q-s)==1 and f)or(g==o and q==s and f)or(g==o and q==s and t-r==(-2 if u else 2)and r==(6 if u else 1)):
   w()
   if t==(0 if u else 7):j[t][s]="q"if u else"Q"

```

To play, enter four space-delimited numbers, the first 2 being the coordinates of the piece you want to move, and the second 2 being where you want it to move to.

# Answer
> 6 votes
Sorry for the delay.

The program is called ChesSkelet. Currently it uses 352 bytes for both code and data. It's written in Z80 Assembly, and particularly for the ZX Xpectrum.

If you don't feel like compiling it and loading it in an emulator you can play online in ChesSkelet site (http://chesskelet.x10host.com).

The program is pretty simple, a big loop where: \- alternatively (1) white inputs its move or (2) black runs it's micro AI to move. \- board is updated in screen. again, there is a huge guide describing the program and techniques in the website.

<pre><code>; ----------------------------------------------------------------------------- ; CHESSKELET /tseske'let/ ; Alex Garcia (reeagbo), Boria Labs 2018-2019 ; Thanks, @MstrBlinky and @johan_koelman, for your contribution ; Developed with ZXSpin, Notepad++ ; ----------------------------------------------------------------------------- ; Compilation with ZXSpin (all versions) and SpectNetIde (not all versions) ; Run with RANDOMIZE USR 30000 ; ----------------------------------------------------------------------------- ; debug mode: 0 = no, 1 = yes debmod equ 0 ; gramod: 0 = minimal interface, 1 = basic interface, 2 = full interface gramod equ 0 ; feamod: 0 = no features (if fails at legadd 'ret'), 1 = all features feamod equ 0 ; ROM memory addresses clescr equ 3503 laskey equ 23560 ; memory micro-pages (256B, typically H register) used for simple memory access auxsth equ $7D piearh equ $7E movlih equ $7F boasth equ $80 boaath equ $81 boaoph equ $82 canlih equ $83 org 30000 ; code is not directly portable ;------------------------------------------------------------------------------ ; Common code before turns ;------------------------------------------------------------------------------ ; legal moves generation (3B) ----------------------------------------- befmov call genlis ; candidate move list, used for both sides ; switch sides on every loop (6B+1B) ---------------------------------- whomov ld l, h ; (H)L: $7F7F = movlih + gamsta, ++ ld a, (hl) ; load state xor h ; (@johan_koelman) switch turn: bla=0, whi=1 ld (hl), a ; save state back in memory if feamod>0 jp z, blamov else jr z, blamov ; if 0, jump to black moves, jp maybe endif ; clear screen (3B) whimov call clescr ; ROM routine set screen mode ; print board ----------------------------------------------------------------- priboa ; A, B = 0 at this point ; initialization (4B) ld h, boasth ; H(L)= $80, L always 0, load board ++ ld d, piearh ; D(E): piece array pointer, E o/w later priloo ; print colored squares (8B) if gramod>0 ; opt: print colored squares ld a, 19 ; set bright ASCII code rst 16 ; print value ld a, c ; (@MstrBlinky) C is always $21 inc c ; change C parity and %00000001 ; keep Ab0, alternatively 0/1 rst 16 ; print value endif ; print piece (10B) ld a, (hl) ; load piece and %00100000 ; keep color, pih ld b, a ; Bb5: isolate piece color ld e, (hl) ; load piece res 5, e ; uncolor, pih ld a, (de) ; load piece character sub b ; capitalize (-32) only for white pieces rst 16 ; print piece ; next square, end of rank/board detection (15B+1B) inc l ; next square jp m, pricoo ; (@johan_koelman) end of 16x8 board, A=128? ld a, l ; (@MstrBlinky) and $08 ; 8 if end of rank, 0 other cases jr z, priski ; skip if not end of the rank add a, l ; ld l, a ; return result to L ld a, 13 ; A=
    rst 16          ; print char

if gramod>0         ; opt: print colored squares, end of the rank
    inc c           ; change C parity
endif

priski  jr priloo       ; loop through all squares

; print coords (28B+6B)--------------------------------------------------------
pricoo              ; (@MstrBlinky simplified it)
if gramod>0         ; opt: print board coords
    ld bc, $0709        ; B: loop count, C: fixed rank/col

nextce  ld a, $16           ; ASCII control code for AT
    rst 16              ; print it
        ld a, b         ; set rank
        rst 16              ; print it
        ld a, c         ; set column
        rst 16              ; print it
    ld a, '8'       ; base rank
    sub b           ; decrease rank character (8..1)
    rst 16          ; print rank value

    ld a, $16           ; ASCII control code for AT
        rst 16              ; print it
        ld a, c         ; set rank
        rst 16              ; print it
        ld a, b         ; sets column
        rst 16              ; print it
    ld a, 'a'       ; base column character
    add a, b        ; increase rank character (a..h)
    rst 16          ; print rank value

    dec b           ; loop 8 times
    jp p, nextce        ;
endif

if gramod>0         ; opt:  + "?" for input prompt
    ld a, 13        ; A: set  ASCII code
    rst 16          ; prints it to go to the next line for input
    ld a, '?'       ; set "?" ASCII code
    rst 16          ; print it
endif
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
;               WHITE MOVES
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; read chars from keyboard and stores them (16B(+4B+4B))-----------------------
    ; 4 times loop for coord input (3B)
    ld b, 4         ; loop count
    dec d           ; D(E)= $7D =auxsth, E always 0 ++

    ; read key from keyboard loop (8B)
realoo  ld hl, laskey           ; LASTKEY system variable ++
    xor a           ; A=0
    ld (hl), a      ; reset LASTKEY, two birds with 1 stone
wailoo  add a, (hl)             ; load latest value of LASTKEY.
    jr z, wailoo            ; loop until a key is pressed.

    ; skip move/switch sides (4B)
if feamod>0         ; opt: special move, switch sides to play black
    cp 's'          ; if "s" pressed at any time
    jp z, aftmov        ; skip white's move, ### jr maybe
endif
    ; save pressed key and print it (5B)
    inc de          ; (@MstrBlinky) next char, E = 1 to 5
    ld (de), a      ; save char in string
    rst 16          ; print it

    djnz realoo     ; loop for 4 input chars

    ; border reset (4B)
if gramod>1         ; opt: border reset after first white move
    ld a, 7         ; set back to white
    out (254), a        ; set border back to white
endif

; translate coords to square (17B) --------------------------------------------
movchk  ex de, hl       ; (@MstrBlinky routine) DE=end of input string

movloo  ld a, 56        ; rank calc = 8-(rank input-48) = 56-(HL)
    sub (hl)        ; A= 56 - (HL)
    rla         ; move it to high nibble (x16)
    rla         ;
    rla         ;
    rla         ;

    dec hl          ; (@MstrBlinky) run backwards through string
    add a, (hl)     ; rank + column (not 0-7 column)
    sub 'a'         ; make it a 0-7 column

    ld c, b         ; slide results through B and C
    ld b, a         ; at end of 2nd loop everything is in place

    dec l           ; (@MstrBlinky) beginning of input string?
    jr nz, movloo       ; if not, loop again

; search white move in legal move list (24B) ----------------------------------
if feamod>0         ; opt: validate white move
seamov  ld hl, canlis       ; canli pointer ++
    ld a, (hl)      ; number of candidates
    ;inc hl         ; skip to first candidate (+2 bytes)
    ;inc hl         ; removed v0.808, no move in those two bytes

sealoo  ld d, (hl)      ; origin candidate move
    inc hl          ; next byte
    ld e, (hl)      ; target candidate move
    inc hl          ; next byte, for next loop

    ex de, hl       ; candidate pair, DE: HL-canli pointer
    or a            ; reset carry
    sbc hl, bc      ; compare input move with cand. move (Z)
    ex de, hl       ; revert back, canli pointer
    jr z, aftsid        ; move match: jump out. ready to move
                ; B (origin sq), C (target sq) ready here
    dec a           ; count down
    jr nz, sealoo       ; loop until canli covered

    jp whimov       ; if not found, back to move input, jp maybe
else                ; opt: skip validate white move
    jr aftsid       ; Outputs: B: origin square, C: target square
endif
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
;               BLACK MOVES
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
blamov
chomov  ; preparations (7B)----------------------------------------------------
    ld hl, canlis       ; candidate list. No H reuse ++
    ld b, (hl)      ; number of candidates at position 0
    ld c, l         ; C=0, maximum valuation reset
    inc hl          ; skip 2 bytes to first candidate in list
    inc hl          ;
choloo  ; loop through candidates (6B) ----------------------------------------
    ld d, (hl)      ; D: origin candidate square
    inc hl          ; next candidate byte
    ld e, (hl)      ; E: target candidate square
    inc hl          ; next candidate byte
    push bc         ; BC released
    push hl         ; HL is different from here
    ; pieces valuation ----------------------------------------------------
    ; pieces collection (8B)
evatap  ld h, boasth        ; board base ++
    ld l, e         ; target square
    ld b, (hl)      ; black piece value
    ld l, d         ; origin square
    ld c, (hl)      ; white piece value
    res 5, c        ; uncolor white piece; pih

    ; origin attacked square (7B)
evaato  ld a, b         ; target piece always counts
    ld h, boaoph        ; H(L): attacked board base, L: unchanged ++
    bit 7, (hl)     ; target square attacked?
    jr z, evaatt        ; not attacked, skip counting origin piece

if feamod=1         ; opt: rows 2 do not move even if attacked
    ld a, d         ; 0rrr0ccc, add origin square
    and $70         ; filter ranks
    cp $60          ; is rank 6?
    ld a, b         ; target piece always counts
    jr z, evaexi        ; skip this move
endif

    ; count origin piece (1B) if attacked, general case
evaatc  add a, c        ; A: 00pppppp, count white

    ; target attacked square (6B)
evaatt  ld l, e         ; H(L): point at target square
    bit 7, (hl)     ; target square attacked?
    jr z, skiato        ; if target not attacked, skip
    sub c           ; if target attacked, count white out

    ; compensate + prioritize piece valuation(6B)
skiato  ld h, $20       ; prepare H for later rotation and use for A
    add a, h        ; A: 00pppppp, compensate=K+1, pih
    rlca            ; leave space for square weight
    rlca            ; A: pppppp00, piece addition is 5 bits
    ld b, a         ; B: piece addition value
evacol  ld a, e         ; A: 0rrr0ccc
    ; these two values below can be tuned for different opening schemes
    if feamod>0
        add a, 2        ; A: 0rrr0ccc
        and 5           ; A: 00000ccc
    else
        inc a           ; A: 0rrr0ccc
        and 4           ; A: 00000cc0 (weight: 0,0,0,4,4,4,4,0)
    endif

    ; ranks weight (ranks weight is 8..1, aiming for board's end)
evarnk  add hl, hl      ; HL: 00100000 0rrr0ccc (before)
    add hl, hl      ;
    add hl, hl      ; HL: 000000rr r0ccc000 (after)
    sub h           ; A:  00000cww (w=r+c)
    add a, b        ; total value: pieces + weight

    ; maximum value comparison (12B)
evaexi  pop hl          ; recover canli
    pop bc          ; recover previous maximum value
    cp c            ; compare with current maximum
    jr c, chonoc        ; if current eval (A) <= max eval (C), skip

    ld c, a         ; update best evaluation
    pop af          ; remove old maximum to avoid cascades in stack
                ; ### initial push to compensate?
    push de         ; push best candidates so far

chonoc  dec b           ; decrease loop counter 2 by 2.
    djnz choloo     ; loop through all candidates (canto)

    pop bc          ; recover saved values (B: origin, C: target)

; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
;               AFTER SIDES
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; move piece (8B) -------------------------------------------------------------
    ; inputs here: B: origin square, C: target square
    ; write origin square and read piece in it (4B)
aftsid  ld h, boasth        ; point at board (canlih=$83 before) ++
    ld l, b         ; point at origin square

    ; castling, rook moves, v0.800 (26B)
    ; very innacurate as it may cause false moves
if feamod>0         ; opt: castling, rook move
casroo  ld a, (hl)      ; origin piece
    add a, b        ; + origin square
    sub c           ; - target square
caslon  cp $38          ; $36(king) + $74(ori) - $72(tar)= $38, pih
    jr nz, cassho       ; no long castling
    ld l, $70       ; long castling rook square (a1)
    ld (hl), d      ; erase rook (D=0 here)
    ld l, $73       ; rook destination (d1)
    ld (hl), $25        ; move rook, pih
cassho  cp $34          ; $36(king) + $74(ori) - $76(tar)= $34, pih
    jr nz, casend       ; no short castling
    ld l, $77       ; short castling rook square (h1)
    ld (hl), d      ; erase rook (D=0 here)
    ld l, $75       ; rook destination (f1)
    ld (hl), $25        ; move rook, pih
casend
endif

if feamod>0         ; opt: special move: prom, no under-prom (12B)
    ld a, c         ; A: 0rrr0ccc
    and %01110000       ; A: 0rrr0000
    add a, (hl)     ; A: 0rrxpppp
    cp $22          ; white pawn ($22) on rank 8 ($00), pih
    ld l, b         ; restore origin square
    ld d, (hl)      ; original piece
    ld (hl), 0      ; write origin piece
    jr nz, aftdes       ; if not a pawn, skip
    ld d, $27       ; make piece a queen, pih
else                ; opt: write origin piece, no promotion (3B)
    ld d, (hl)      ; D: get origin piece
    ld (hl), 0      ; write origin piece
endif

    ; write target square with origin piece (5B)
aftdes  ld l, c         ; (H)L: target square

    ; checkmate with exit (3B), board is not updated in screen
chkmat  bit 4, (hl)     ; captured piece is king ($16)?, pih
    ret nz          ; (@johan_koelman) return prompt at check mate

aftnok  ld (hl), d      ; write target square
    call genlis     ; update attacked matrix after move
aftmov
; reverse board (22B)----------------------------------------------------------
revboa  ; push full board to stack (7B)
    inc h           ; H = $80 = boasth ++
    ld l, h         ; (H)L: end of board. trick: start from $8080
revlo1  dec l           ; countdown squares
    ld a, (hl)      ; read piece
    push af         ; copy piece to to stack
    jr nz, revlo1       ; loop down to beginning of the board

    ; collect board back ir reverse order + switch color (15B)
    ld l, $78       ; (H)L: end of board again
revlo2  pop af          ; collect piece from stack
    or a            ; is it an empty square?
    jr z, revski        ; if yes, skip
    xor %00100000       ; otherwise, reverse color (b5), pih
revski  dec l           ; countdown squares
    ld (hl), a      ; piece back into board
    jr nz, revlo2       ; loop until beginning of board

    jp befmov       ; back to white move, too far for jr

; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
;               AUXILIARY ROUTINES
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------

; genlis: generates list of legal moves (92B + 9B) ----------------------------
; it was not possible to use it in two different places, only procedure in code
genlis
bacata  ; backup attack board in reverse order, used in evaluation (13B)
    ld l, $FF       ; (H)L = $80FF (boaata-1), H always $80
    ld de, boaopo + $78 ; DE: same thing, 1B passed end of board
bacloo  inc hl          ; HL: increase 16b counter to hop to next page
    dec e           ; E:  decrease 8b counter to hit Z flag
    ld a, (hl)      ; load attack status
    ld (hl), 0      ; clear attack status, no alternative!
    ld (de), a      ; backup attack status
    jr nz, bacloo       ; loop down to square $00
                ; exit values: DE=$8200, HL=$8177

    ; prepare environment (4B)
    inc d           ; D= $83= canlih
    xor a           ; reset
    ld (de), a      ; cantot= 0
    ld b, l         ; B= L = 77, SQUARE COUNT

    ; read piece from board (4B)
squloo  ld h, boasth        ; H: board base ++
    ld l, b         ; point at current loop square
    ld a, (hl)      ; read piece from board

    ; king castling, v0.800 (15B)
    ; only basic rule: no unmoved pieces or attacked squares check
    if feamod>0
    kincas  ld l, a     ; save A (can't use push AF, flags lost)
        add a, b    ; A: 0rrr0xxx + 000ppppp (uncolored white p.)
        cp $AA      ; king($36) at E1($74)= $AA, pih
        ld a, l     ; recover A
        jr nz, kinend   ; if no match, skip adding legal move

        ld c, $72   ; E1-C1 move, rook's move missing
        call legadd ; add king's move
        ld c, $76   ; E1-G1 move, rook's move missing
        call legadd ; add king's move and go on with king's moves
    kinend
    endif

    ; get move type and pointer to move list (6B)
squgon  dec h           ; H(L)= movlih, moves vector base ++
    add a, a        ; x4, each piece vector is 4B long
    add a, a        ;
    ld l, a         ; (H)L points at the move vector now

    ld d, 2         ; 2 submoves per piece
subloo      ; byte 1 - move type (5B)
        ld a, (hl)      ; move type loaded
        or a            ; =cp 0, 2nd move type not used case
                    ; black/empty: move type=0 leads here
        jr z, squexi        ; ---v exit: square is done
        ld e, a         ; E: MOVE TYPE (B,C,D used here)

        ; pawn 2 squares forward - move type modified (8B)
        if feamod>0     ; opt: special move, pawn 2 sq. forward
        genpw2  add a, b    ; piece square + move type
            and %11111000   ; masked with relevant bits
            cp $88      ; $28(str.pawn)+$60(rnk 6) ### univocal
            jr nz, skppw2   ; if not, skip
            inc e       ; increase radius: 1 -> 2
        skppw2
        endif

        ; byte 2 - movlis delta (3B)
        inc hl          ; next piece sub-entry
        push hl         ; Save HL for 2nd loop
        ld l, (hl)      ; pointer to move delta

vecloo          ; vector read (8B)
            ld c, b     ; TARGET SQUARE init
            ld a, (hl)  ; vector delta
            or a        ; =cp 0
            jr z, vecexi    ; ---v exit: vectors end with 0, next sq.
            push hl     ; save current delta
            push de     ; save move type + radius
                    ; E: variable radius within loop
            ld d, a     ; D: store delta within loop

celloo              ; prepare x88 check (7B)
                ld a, d     ; delta loaded
                add a, c    ; current target (sq. + delta)
                ld c, a     ; current target
                and $88     ; 0x88, famous OOB trick
                jr nz, vecnex   ; ---v exit: OOB, next vector

                ; read target square (3B)
                inc h       ; H(L)= $80 = boasth ++
                ld l, c     ; point at target square
                ld a, (hl)  ; read target square content

                ; mark attacked ### str. pawn marked attacked
                    inc h       ; H(L)= $81 = boaath ++
                    ld (hl), h  ; mark attacked ($81)
                    dec h       ; H(L)= $80 = boasth ++

                dec h       ; H(L)= $79= movlih ++
                ; target is white (4B)
                bit 5, a    ; is it white?, pih
                jr nz, vecnex   ; ---v exit: WHITE b4=1, next vector

                ; target not white (3B)
                or a        ; =cp 0, is it empty?, pih
                jr z, taremp    ; if not 0, it's black: legal, no go on

tarbla              ; target is black (7B)
                bit 5, e    ; special move: pawn straight check
                jr nz, vecnex   ; ---v exit: no straight capture, next vector
                ld e, a     ; make radius=0 (=<8 in code, canonical: ld e, 0)
                jr legadj   ;

taremp              ; target is empty (14B)
                bit 4, e    ; special move: pawn on capture check
                jr nz, vecnex   ; ---v exit: no diagonal without capture, next vector
                dec e       ; decrease radius
legadj
                if feamod=0 ; opt: legadd for basic model
                ; add candidate (B: current square, C: target square) (9B)
                    push hl
                    ld hl, canlis   ; HL: start of candidate list. No H reuse ++
                    inc (hl)    ; +2 to candidate counter to move to next
                    inc (hl)    ; first free position in list
                    ld l, (hl)  ; point at free position

                    ld (hl), b  ; 1) save origin square
                    inc hl      ; move to next byte
                    ld (hl), c  ; 2) save dest square
legend                  pop hl      ; recover HL=pointer to vector list
                else        ; opt: legadd call for full model
                    call legadd
                endif

                bit 3, e    ; if radius < 8 (Cb3=0), radius limit
                jr nz, celloo   ; ---^ cell loop

vecnex          ; next vector preparation (5B)
            pop de      ; DE: recover move type + radius
            pop hl      ; HL: recover current vector
            inc hl      ; HL: next vector
            jr vecloo   ; ---^ vector loop

vecexi  ; next square preparation (5B)
    pop hl          ; HL: recover pointer to sub-move list
    inc hl          ; HL: next byte, point at 2nd sub-move
    dec d           ; 2 sub-move iterations loop control
    jr nz, subloo       ; if not 2nd iteration, repeat loop
    ; end of loop (2B)
squexi  djnz squloo     ; ---^ squares loop
    ret

; legadd: add legal move -------------------------------------------------------
if feamod>0         ; legadd for king castling
legadd              ; (B: current square, C: target square)
    push hl
    ld hl, canlis       ; HL: start of candidate list. No H reuse ++
    inc (hl)        ; +2 to candidate counter to move to next
    inc (hl)        ; first free position in list
    ld l, (hl)      ; point at free position

    ld (hl), b      ; 1) save origin square
    inc hl          ; move to next byte
    ld (hl), c      ; 2) save dest square
    pop hl          ; recover HL=pointer to vector list
    ;ret            ; <===== not removed with feamod=0
endif

; -----------------------------------------------------------------------------
; DATA ------------------------------------------------------------------------
; -----------------------------------------------------------------------------

; Memory page: 7700h ----------------------------------------------------------
org $7700
auxstr              ; input string stored here

; Memory page: 7E00h ----------------------------------------------------------
; used to convert values to pieces
org $7E00
if gramod=0         ; opt: space or dot depending on the size
piearr  defb '.'        ; $2B
else
piearr  defb ' '
endif
org $7E02
    defm "pnbr"     ; change this array to any language, pih
org $7E07
    defb 'q'        ; change this array to any language, pih
org $7E16
    defb 'k'        ; change this array to any language, pih

; Memory page: 7F00h ----------------------------------------------------------
; sub-moves and vectors
org $7F00
; leave empty $00-$04-...-$24 for black pieces/empty square pointers
org $7F88           ; pawn: $22x4=$84
; piece, move type, vector list delta address (18B)
; move type / 0 / 0 / pawn straight / pawn diagonal / DDDD (real radius + 7)
movlis
pawgen  defb    $28, $E3    ; pawn straight
    defb    $18, $E7    ; pawn capture
org $7F8C
knigen  defb    $08, $EA    ;
org $7F90
bisgen  defb    $0E, $E5    ; bishop
org $7F94
roogen  defb    $0E, $E0    ; rook
org $7F9C
quegen  defb    $0E, $E0    ; queen
    defb    $0E, $E5    ;
org $7FD8
kingen  defb    $08, $E0    ; king: $($16+$20)x4=$D8
    defb    $08, $E5    ;

org $7FE0           ; vectors start at: $7FE0 (arbitrary)
; (y, x) move delta pairs (16B)
veclis
strvec  defb    $FF, $01    ; +0, straight vectors
    defb    $10, $F0    ; +3, straight pawn, last half line
org $7FE5
diavec  defb    $0F, $11    ; +5, diagonal vectors
    defb    $EF, $F1    ; +7, diagonal pawn
org $7FEA
knivec  defb    $E1, $F2    ; +10, knight vectors
    defb    $12, $21    ; knight moves listed clockwise
    defb    $1F, $0E    ;
    defb    $EE, $DF    ;
; board status: 0000000 / turn (B=0, W=1)
org $7F7F
gamsta

; Memory page: 8000h ----------------------------------------------------------
    ; board squares format: 00cppppp
    ; pppp (value) : pawn=2, knight=3, bishop=4, rook=5, queen=7, king=$16
    ; c (color): white=1, black=0
    ; initial board setup
if debmod=1         ;opt: fill board for debugging
    org $8000
    boasta  defb $00, $00, $00, $00, $00, $00, $00, $00 ; <--8
        defb $00, $00, $00, $00, $00, $00, $00, $00
        defb $00, $00, $00, $00, $02, $00, $00, $00 ; <--7
        defb $00, $00, $00, $00, $00, $00, $00, $00
        defb $00, $00, $00, $23, $00, $00, $00, $00 ; <--6
        defb $00, $00, $00, $00, $00, $00, $00, $00
        defb $00, $00, $00, $00, $00, $00, $00, $00 ; <--5
        defb $00, $00, $00, $00, $00, $00, $00, $00
        defb $00, $00, $00, $00, $00, $00, $00, $00 ; <--4
        defb $00, $00, $00, $00, $00, $00, $00, $00
        defb $00, $00, $00, $00, $00, $00, $00, $00 ; <--3
        defb $00, $00, $00, $00, $00, $00, $00, $00
        defb $00, $00, $00, $00, $00, $00, $00, $00 ; <--2
        defb $00, $00, $00, $00, $00, $00, $00, $00
        defb $00, $00, $00, $00, $00, $00, $00, $00 ; <--1
else                ; opt: reduces board size for gameplay
    org $8000
    boasta  defb $05, $03, $04, $07, $16, $04, $03, $05
    org $8010
        defb $02, $02, $02, $02, $02, $02, $02, $02
    org $8060
        defb $22, $22, $22, $22, $22, $22, $22, $22
    org $8070
        defb $25, $23, $24, $27, $36, $24, $23, $25
endif

; Memory page: 8100h ----------------------------------------------------------
org $8100
boaata              ; attacked squares board

; Memory page: 8200h ----------------------------------------------------------
org $8200
boaopo              ; reversed attacked squares board

; Memory page: 8300h ----------------------------------------------------------
; candidate move list at the very end of the program
org $8300
canlis  equ $
````
</code></pre>

# Answer
> 3 votes
## \>\<\>, 1467 bytes

Well, it doesn't quite break the 487-byte record…

```
>   "  :W"av
"RNBQKBNR"a/
"PPPPPPPP"a/
"        "a/
"        "a/
"        "a/
"        "a/
"pppppppp"a/
"rnbqkbnr"a/
   l?!vo29.>
v?)b:i<~
\:8c*-:i:}4c*-:@g:o" "o{{oo" "o}i:o8c*-i:o4c*-
\{:"^")80g"^")-?X
\:"^")48**-
\&3[:}]$:@=3[:}]{:}=*?X&
\:"Q"=?v:"R"=?v
v      >      >&r:4[:}]$-r:4[:}]-{:?!v$:?!v~~&
 ["+-+10"]?$~137*.*731$~$?]"10+-+"[1)<    >)1
\:"Q"=?v:"B"=?v
v      >      >&$:@$:@-r$:@$:@$-{-r4[r$:@$:@+r$:@$:@+{-}]{:?!v$:?!v~~&
 )1["+-11"]?$137*.                     .*733]~~r?{"--11++"[1)<    >
 \>42b*p72b*p32b*p62b*p{{$:@$:@}}4[r
 >$zz$zz$:@{:}=$:@5[:}]=*?v$:@$:@g" "-?X
               .+9*a29$]~~<
\&$:@{:}-:*$:@5[:}]-:*+&
\:"N"=?v
  X?-5&<v
\:"K"=?v
  X?)3&<v
  )-?vX >$:@$:@g:" "=?v"^")80g"^"
     >049*.*942      ~<
\:"P"=?v
 )?X:1=\&~$:@{:}-:*$:@5[:}]80g"^")?$-:2
X      \?v2-?X?X$:@$:@80g"^"(2*1--g" "-?Xv
         >~:?v?X                         >$:@$:@g" "-?Xv
  @@?$~&049*.>1-?X$:@$:@g:" "=?X"^"(80g"^"(=?X         >:880g"^")7*-=&"Q"
\>&80g"^"):&48**+@p" "@p0
>:8%1+$:8,:1%-1+$}$:@$:@g"Kk"&:&?$~=?v~~1+:88*=?X
v                {{1030014103431434~{<
>l2=?v$:@$:@}}$@+2-a%@+2-a%$g"nN"&:&?$~=?X{{
\    >0010200121021222{{
>l2=?v$:@$:@}}$@+1-@+1-$g"kK"&:&?$~=?X{{
v    >$:@1+$:@&:&2*1--g"pP"&:&?$~=?X$:@1-$:@&:&2*1--g"pP"&:&?$~=?X
\"10++r10-+r01++r01+-r11++b11+-b11-+b11--b"
>l2=?v48*4a*6+p44*4a*6+p74a*6+\
   /} }@:$@:${{p+6*a46p+6*a4fp/
 -?\$ zz:9%?!v$zz:9%?!v$:@$:@g:"y"&:&48**-=?X:"q"&:&48**-=?X" "
^~~<         <        <
v    >~~"bW"&?$~80paaoo

```

Try it at the fish playground! (It makes use of a couple of bugs in that interpreter, so I can't promise it'll work anywhere else. You'll probably want to run it at maximum speed — it can take over a minute to do one move.)

When you run the code, it will print

```
rnbqkbnr
pppppppp

PPPPPPPP
RNBQKBNR

W:

```

Capital letters represent white, lowercase represent black. You can then give your move as input in the form `[a-h][1-8][a-h][1-8]`, e.g. `e2e4`, meaning "move the piece at `e2` to `e4`". The program will then print, for example,

```
W:  P e2 e4

rnbqkbnr
pppppppp

    P

PPPP PPP
RNBQKBNR

b:

```

The main form of memory in \>\<\> is the stack; however, that's not very practical for storing a chess board. Instead, I used \>\<\>'s self-modifying capability to store the chess board as part of the source code itself, accessing it with `g` and `p`.

The bulk of the code is to check whether your move is legal. There are several things to check here:

* Are you trying to move a piece that really exists, and is it yours (line 12, 0-indexed)?
* Are the start and end squares different (line 14)?
* Is the move in the right direction for the type of piece (orthogonal for rook and queen, lines 15–17; diagonal for bishop and queen, lines 18–20; L-shaped for knight, lines 24–26; 1 square for king, lines 27–28; or a pawn move, lines 31–35)?
* Are the squares between the start and end all empty (for rook, bishop, queen — lines 21–23)?
* Is the target square empty or occupied by an enemy (lines 29–30)?
* Are you in check after the move (lines 36–47)?

If any of those questions have the wrong answer, the program throws an error and halts; otherwise, it edits the chessboard in its source code, prints it again and waits for the next move.

For the king and knight moves, I borrowed Level River St's trick of checking the squared Euclidean distance: for a king, it's less than 3, and for a knight, it's exactly 5.

# Answer
> 2 votes
# C, 598 bytes

I shaved 2 characters from the best answer (598) by changing the `for(;1;)` to `for(;;)` and `t^=32` to `t^=w`

I win! :)

```
n=8,t=65,s,f,x,y,p,e,u=10,w=32,z=95;char a[95],b[95]="RNBKQBNR";v(){p=a[s]&z;y=f/u-s/u;x=f-s-y*u;e=x*x+y*y;n=s%u/8|f%u/8|a[s]/w-t/w|a[f]/w==t/w|!(p==75&e<3|p>80&x*y==0|p%5==1&x*x==y*y|p==78&e==5|p==80&x*(z-t)>0&(a[f]-w?e==2:e==1|e==4&s%5==1));if(!n&&p-78)for(e=(f-s)/abs(x*x>y*y?x:y),x=s;(x+=e)-f;)n|=a[x]-w;}main(){for(a[93]=40;n--;a[92]=47)sprintf(a,"%s%cP    p%c \n",a,b[n],b[n]+w);for(;;){puts(a);for(n=1;n;){putchar(t);scanf("%d%d",&s,&f);v();memcpy(b,a,z);if(!n){a[f]=p-80|f%u%7?a[s]:t+16;a[s]=w;a[f]&z^75||(a[z-t/w]=f);f=a[z-t/w];t^=w;for(n=1,s=80;n&&s--;)v();if(n=!n)memcpy(a,b,z),t^=w;}}}}

```

Output

```
RP    pr
NP    pn
BP    pb
QP    pq
KP    pk
BP    pb
NP    pn
RP    pr

A31 32
RP    pr
NP    pn
BP    pb
Q P   pq
KP    pk
BP    pb
NP    pn
RP    pr

a36 35
RP    pr
NP    pn
BP    pb
Q P  p q
KP    pk
BP    pb
NP    pn
RP    pr

A

```

---
Tags: code-golf, chess
---


title: Tips for golfing in K

text:
# Question
Title: Tips for golfing in K
K is a programming language in the APL family designed by Arthur Whitney. While the official interpreter is closed-source and commercial, a trial version with a workspace limit of 32 bits of addressing space (which shouldn't pose problems for code golf) can be found at the Kx Systems website. This version bundled as part of the kdb+ database is colloquially known as "K4". There are also open-source K implementations available, including Kona, which is based on K3, and my own interpreter called oK, which is based on K5 and has a browser based REPL.

Kx Systems has a wiki with K4/kdb+/Q information, and the Kona GitHub page also has an excellent collection of reference materials. I have begun writing a manual for oK/k5 which may be a useful reference.

Like  and APL, K is a very terse and powerful language, and can often make a good showing in code golf. Please share tips, tricks and idioms you discover, and if you haven't tried K before consider giving it a spin! Post one tip per answer, please!

# Answer
> 8 votes
# Calling a Dyad

Assuming you had a dyadic (2-argument) function `f`:

```
f: {x+2*y}

```

You would ordinarily call it like so:

```
f[3;47]

```

You can save a character by instead currying in the first argument and then applying the resulting partial function to the second argument by juxtaposition:

```
f[3]47

```

The same naturally works for array indexing:

```
  z: (12 17 98;90 91 92)
(12 17 98
 90 91 92)

  z[1;2]
92

  z[1]2
92

```

# Answer
> 6 votes
# Ranges

Normally if you want to create a vector of sequential numbers you use `!`:

```
  !5
0 1 2 3 4

```

If you want to create a range that starts at a number other than zero, you'd then add an offset to the resulting vector:

```
  10+!5
10 11 12 13 14

```

There are a few unusual approaches which could work better for a particular situation. For example, if your base and offset are already members of a list, you could use "where" twice:

```
  &10 5
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1
  &&10 5
10 11 12 13 14

```

For slower-growing sequences, consider combining "where" with "take":

```
  5#2
2 2 2 2 2
  &5#2
0 0 1 1 2 2 3 3 4 4

```

If you want to create a range of multiples, you could multiply the result of `!` or you could scan (`\`) a list of copies of the step size:

```
  2*!5
0 2 4 6 8
  +\5#2
2 4 6 8 10

```

If you're trying to avoid parentheses, the former is better if the length of the sequence is variable and the step size is fixed, while the latter is better if the step size is what tends to vary. Picking the right variation can save 1 or 2 characters. The off-by-one difference could also work in your favor.

# Answer
> 6 votes
# Printing newlines

If your output *must* have a newline, you may be tempted to do this:

```
`0:whatever,"\n"

```

*Don't*. K2 (and likely other versions) has a neat feature where you can print a list of lines:

```
  `0:("abc";"def")
abc
def

```

So, if you need to append a newline to the output, just do:

```
`0:,whatever

```

# Answer
> 6 votes
# Trainify `(x;f x)` and `x f g x`

*Works in ngn/k*

You can use "n-times-scan" `1 f\x` for this. It is slightly (likely just 1 byte) longer but more reliable than converge scan `f\x` because it is guaranteed to return the two-item list `(x;f x)` even if `x~f x` or `~x~f f x`.

For example, if you want to extract the first and last items of a list:

```
{(*x;*|x)}   /10 bytes
{*'(x;|x)}
{*'1|:\x}    /9 bytes
*'1|:\       /6 bytes (8 if you need enclosing parens)

```

Note that `*'|:\` doesn't always work because the reverse might be identical to itself, in which case a 1-item list is returned instead of two.

This trick extends to the case `x f g x`, which can be translated to `f/(x;g x)` and then `f/1 g\x`, though it actually saves bytes only if `g` does not require `(...)` in `g\`.

For sorting a list of lists by the result of `-/` of each row:

```
{<x!-/'x}   /9 bytes, or 10 with `@`
<!/1-/'\    /8 bytes, or 10 with `(...)`

```

Both are real examples from this answer.

---

Sometimes `f\` works unconditionally in place of `1 f\`.

```
/absolute value
{x|-x}
|/-:\

```

`x f x` is shorter to trainify as `f/2#,` than `f/1::\`.

```
/equality table
{x=/:x}
=/:/2#,

```

`(f x)g x` is only one byte longer than `x g (f x)` as a train: `g/|1 f\`.

```
/extract first interval based on the indices computed by f
{*(f x)_x}
{*f[x]_x}
*_/|1 f\

```

# Answer
> 3 votes
## Cyclic Permutations

Dyadic `!` in K2/K3 is "rotate":

```
  2!"abcd"
"cdab"
  -1!"abcd"
"dabc"

```

When "scan" (`\`) is provided with a monadic verb, it acts as a fixed-point operator. In K, fixed point operators repeatedly apply their verb to a value until the initial value is revisited or the value stops changing. Combining rotate with fixed-point scan provides a very convenient way of computing a set of cyclic permutations of a list:

```
  ![1]\1 2 4 8
(1 2 4 8
 2 4 8 1
 4 8 1 2
 8 1 2 4)

```

You can either curry `!` via brackets or parenthesize to create the verb train `(1!)`:

```
![1]\
(1!)\

```

(Note that `1!\` has an entirely different behavior!) Each of these is equivalent in length but the former may be more desirable if the rotation stride is something other than 1; in this case the brackets delimit a parenthesized subexpression "for free".

As an example, here is a short program which tests via brute force whether a string x contains the substring y (cyclically!):

```
{|/(y~(#y)#)'![1]\x}

```

K5 users beware! K5 has changed the meaning of dyadic `!`, so this technique isn't so easy. It will work as expected in Kona.

# Answer
> 3 votes
Casts from strings are expensive. Just use eval. This:

```
0.0$a

```

can become just this:

```
. a

```

In K5, it's a byte shorter:

```
.a

```

# Answer
> 3 votes
# Each Right

Occasionally you may find yourself writing (or arriving at by simplification) a parenthesized expression applied via each-monad:

```
  (2#)'3 4 5
(3 3
 4 4
 5 5)

```

It is one character shorter to convert this pattern into an application of each-right:

```
  2#/:3 4 5
(3 3
 4 4
 5 5)

```

# Answer
> 3 votes
## Lists of Strings

Some challenges call for a hardcoded list of strings, e.g.:

```
("qwertyuiop";"asdfghjkl";"zxcvbnm")

```

Sometimes, a few bytes can be saved using an alternative form, i.e.:

```
";"\:"qwertyuiop;asdfghjkl;zxcvbnm"

```

`k4` (and several other variants) can take advantage of the `symbol` datatype, so long as the hardcoded strings lack spaces. For example:

```
$`qwertyuiop`asdfghjkl`zxcvbnm

```

# Answer
> 3 votes
# Handling unicode characters (ngn/k only)

*Originally from Bubbler.*

Putting unicode characters inside a string turns them into a byte sequence:

```
 "⍺⍴⍵"
0xe28dbae28db4e28db5

```

this often hinders the ability to use them as individual characters. However, you can use symbols instead:

```
 `⍺`⍴`⍵
`0xe28dba`0xe28db4`0xe28db5

```

Which will group them into appropriate characters. You can then retrieve the byte sequences with `$`, and concatenate them into the correct string.

# Answer
> 2 votes
# Avoid Conditionals

K has a conditional construct (`:[`) which is equivalent to a Lisp-style `cond`:

```
:[cond1;result1; cond2;result2; cond3;result3; default]

```

You can have as many conditions as you like, and if none match the default value is returned.

Sometimes (as in recursive programs or programs that otherwise rely on a sequence of side effects), there's no getting around using one of these. However, in situations where you can afford to do a bit of extra work, you can often replace a "cond" with list indexing.

Consider the infamous fizzbuzz program. Written in a conventional imperative programming style, we might go with:

```
{:[~x!15;"FizzBuzz";~x!3;"Fizz";~x!5;"Buzz";x]}'1+!100

```

There's quite a bit of repetition here in the divisibility tests. A different approach recognizes that there are 4 cases (a number, divisibility by only 3, divisibility by only 5, divisibility by 3 and 5) and attempts to directly compute an index which chooses one of these cases from a list:

```
{(x;"Fizz";"Buzz";"FizzBuzz")@+/1 2*~x!/:3 5}'1+!100

```

Two characters shorter, and a better use of the language. Knowing that list literals are evaluated right to left, we also gain some additional golfing opportunities for combining reused subexpressions. We couldn't have easily done this in the cond-based version, since the string cases aren't evaluated at all if they aren't selected:

```
{(x;4#t;4_ t;t:"FizzBuzz")@+/1 2*~x!/:3 5}'1+!100

```

Now we've saved 5 characters overall. Incidentally, this particular example works out even nicer in k5, since we have the "pack" overload for `/` to handle the step of multiplying by a vector of coefficients and summing:

```
{(x;4_t;4#t;t:"FizzBuzz")@2 2/~3 5!\:x}'1+!100

```

Also note that the behavior of "find" (`?`), which produces an index past the end of the key list if the item is not found, is specifically designed to support handling a "default" case in this kind of indexing. Consider this fragment to convert vowels to uppercase:

```
{("AEIOU",x)"aeiou"?x}'

```

Versus one of:

```
{t:"aeiou"?x;:[t<5;"AEIOU"t;x]}'
{:[~4<t:"aeiou"?x;"AEIOU"t;x]}'

```

(I know which I'd rather read, too!)

# Answer
> 2 votes
# Uses of `$`

This tip is written with ngn/k in mind, parts might apply to other versions

* `$x string` applied on a string converts each character into its own string, making `$x` one byte shorter than `,'x` or `++x`.

This transformation can be useful when replacing some characters with spaces in a string: Given a string `x` and a boolean vector `y` of the same length, `($x)@'y` inserts spaces at the indices of 1's in the boolean vector.

```
  ($"Hello")@'0 1 1 0 1
"H  l "

```
* `i$C` truncates strings if `i` is less than the length of string. On strings that case is identical to `i#C`, but when given lists of strings, `$` always applies to individual strings, potentially saving some `'`s.

```
  3$("Hello, ";"World")
("Hel";"Wor")

```

---
Tags: code-golf, tips
---


title: Find the highest unique digit

text:
# Question
Title: Find the highest unique digit
Surprisingly we haven't had a simple "find the highest digit" challenge yet, but I think that's a *little* too trivial.

Given input of a non-negative integer, return the highest **unique** (ie not repeated) digit found in the integer. If there are no unique digits, your program can do anything (undefined behaviour), other than the numbers that are non unique in the input of course.

The input can be taken as a single integer, a string, or a list of digits.

## Test cases

```
12         -> 2
0          -> 0
485902     -> 9
495902     -> 5
999999     -> Anything
999099     -> 0
1948710498 -> 7

```

This is so fewest bytes **in each language** wins!

# Answer
> 16 votes
# Python 3, 40 bytes

Saved 2 bytes thanks to movatica.

```
lambda i:max(x*(i.count(x)<2)for x in i)

```

Try it online!

### 42 bytes

Works for both String and list of digits parameter types. Throws an error for no unique digits, kind of abuses of that spec:

```
lambda i:max(x for x in i if i.count(x)<2)

```

Try it online!

---

## Explanation

* `lambda i:` \- Declares a lambda function with a string or list of digits parameter i.
* `max(...)` \- Finds the maximum value of the generator.
* `x for x in i` \- Iterates through the characters / digits of `i`.
* `if i.count(x)<2` \- Checks if the digit is unique.

# Answer
> 16 votes
# 05AB1E, ~~4~~ 3 bytes

Saved 1 byte thanks to *Mr. Xcoder* notifying that a digit list is valid input.

```
¢ÏM

```

Try it online!

**Explanation**

```
¢     # count occurrences of each digit in input
 Ï    # keep only the digits whose occurrences are true (1)
  M   # push the highest

```

# Answer
> 8 votes
## Alice, 15 bytes

```
/&.sDo
\i-.tN@/

```

Try it online!

### Explanation

```
/...
\.../

```

This is a simple framework for linear code that operates entirely in Ordinal mode (meaning this program works completely through string processing). The unfolded linear code is then just:

```
i..DN&-sto@

```

What it does:

```
i    Read all input as a string.
..   Make two copies.
D    Deduplicate the characters in the top copy.
N    Get the multiset complement of this deduplicated string in the input.
     This gives us a string that only contains repeated digits (with one
     copy less than the original, but the number of them doesn't matter).
&-   Fold string subtraction over this string, which means that each of
     the repeated digits is removed from the input.
s    Sort the remaining digits.
t    Split off the last digit.
o    Print it.
@    Terminate the program.

```

# Answer
> 7 votes
## Retina, 16 bytes

```
O`.
(.)\1+

!`.$

```

Try it online!

### Explanation

```
O`.

```

Sort the digits.

```
(.)\1+

```

Remove repeated digits.

```
!`.$

```

Fetch the last (maximal) digit.

# Answer
> 7 votes
# Charcoal, 18 12 bytes

```
Ｆχ¿⁼№θＩι¹ＰＩι

```

Try it online! (Link to verbose version)

Prints nothing if no solution is found. The trick is that the `for` loop prints every unique number in the input string, but without moving the cursor, thus the value keeps reprinting itself until the final solution is found.

The previous version printed the characters A to Z when no solution was found, hence the comments:

```
ＡααＦχＡ⎇⁼№θＩι¹Ｉιααα

```

Try it online! (Link to verbose version)

# Answer
> 7 votes
# Husk, 7 bytes

```
→fo¬hgO

```

Try it online! (Test suite, crashes on the last test case since it has no unique digits)

This is a composition of functions in point-free style (the arguments are not mentioned explicitely anywhere). Takes input and returns output as a string, which in Husk is equivalent to a list of characters.

### Explanation

```
Test case: "1948710498"

      O    Sort:                             "0114478899"
     g     Group consecutive equal elements: ["0","11","44","7","88","99"]
 fo¬h      Keep only those with length 1*:   ["0","7"]
→          Take the last element:            "7"

```

\*The check for length 1 is done by taking the head of the list (all elements except the last one) and negating it (empty lists are falsy, non-empty lists are truthy).

# Answer
> 7 votes
## JavaScript (ES6), ~~46~~ ~~41~~ 40 bytes

Takes input as a string. Returns RangeError if there are no unique digits.

```
s=>f=(i=9)=>s.split(i).length-2?f(--i):i

```

-7 bytes thanks to Rick Hitchcock

-1 byte thanks to Shaggy

### Test cases

```
let f =

s=>g=(i=9)=>s.split(i).length-2?g(--i):i

console.log(f("12")())         // 2
console.log(f("0")())          // 0
console.log(f("485902")())     // 9
console.log(f("495902")())     // 5
//console.log(f("999999")())   // RangeError
console.log(f("999099")())     // 0
console.log(f("1948710498")()) // 7
```

# Answer
> 7 votes
## Haskell, 37 bytes

```
f s=maximum[x|x<-s,[x]==filter(==x)s]

```

Try it online!

How it works:

```
  [  |x<-s   ]          -- loop x through the input string s
    x                   -- and keep the x where
     [x]==filter(==x)s  -- all x extracted from s equal a singleton list [x]
maximum                 -- take the maximum of all the x

```

# Answer
> 7 votes
# , 41 bytes

```
function(x,y=table(x))max(names(y[y==1]))

```

An anonymous function that takes a list of digits, either as integers or single character strings. It precomputes `y` as an optional argument to avoid using curly braces for the function body. Returns the digit as a string. This takes a slightly different approach than the other R answer and ends up being the tiniest bit shorter! looks like my comment there was wrong after all...

`table` computes the occurrences of each element in the list, with `names(table(x))` being the unique values in `x` (as strings). Since digits are fortunately ordered the same lexicographically as numerically, we can still use `max`.

Try it online!

# Answer
> 5 votes
# Python 3, 40 bytes

```
lambda i:max(x+9-9*i.count(x)for x in i)

```

Only works for lists of digits. The edge case '990' works fine :)

Try it online!

# Answer
> 5 votes
# Husk, 3 bytes

```
►≠O

```

Try it online!

## Explanation

```
►≠O
  O order the elements
►   max by
 ≠  inequality(selects least frequent elements)
    then returns the last of the least frequent elements

```

# Answer
> 4 votes
# Brachylog, 8 bytes

```
ọtᵒtᵍhth

```

Try it online!

### Explanation

```
Example input: 495902

ọ          Occurences:    [[4,1],[9,2],[5,1],[0,1],[2,1]]
 tᵒ        Order by tail: [[0,1],[2,1],[4,1],[5,1],[9,2]]
   tᵍ      Group by tail: [[[0,1],[2,1],[4,1],[5,1]],[[9,2]]]
     h     Head:          [[0,1],[2,1],[4,1],[5,1]]
      t    Tail:          [5,1]
       h   Head:          5

```

# Answer
> 4 votes
## Husk, ~~9~~ 8 bytes

*Thanks to Leo for suggesting a slightly neater solution at the same byte count.*

```
▲‡ȯf=1`#

```

Try it online!

### Explanation

```
  ȯ       Compose the following thre functions into one binary function.
      `#  Count the occurrences of the right argument in the left.
    =1    Check equality with 1. This gives 1 (truthy) for values that
          appear uniquely in the right-hand argument.
   f      Select the elements from the right argument, where the function
          in the left argument is truthy.
          Due to the composition and partial function application this
          means that the first argument of the resulting function actually
          curries `# and the second argument is passed as the second
          argument to f. So what we end up with is a function which selects
          the elements from the right argument that appear uniquely in
          the left argument.
 ‡        We call this function by giving it the input for both arguments.
          So we end up selecting unique digits from the input.
▲         Find the maximum.

```

# Answer
> 4 votes
# APL (Dyalog Unicode), 10 chars = 19 bytes

Method: multiply elements that occur multiple times by zero, and then fine the highest element.

```
⌈/×∘(1=≢)⌸

```

for each unique element and its indices in the argument:

`×` multiply the unique element

`∘(``)` with:

`1=` the Boolean for whether one is equal to

the tally of indices (how many times the unique element occurs)

`⌈/` the max of that

Try it online!

# APL (Dyalog Classic), 15 bytes

```
⌈/×∘(1=≢)⎕U2338

```

Try it online!

Identical to the above, but uses `⎕U2338` instead of .

# Answer
> 4 votes
# Mathematica, 41 bytes

```
(t=9;While[DigitCount[#][[t]]!=1,t--];t)&

```

thanks @Martin Ender

here is Martin's approach on my answer

# Mathematica, 35 bytes

```
9//.d_/;DigitCount[#][[d]]!=1:>d-1&

```

# Answer
> 4 votes
## R, ~~45~~ 43 bytes

`function(x)max(setdiff(x,x[duplicated(x)]))`

Try it online!

Takes input as a vector of integers. Finds the duplicated elements, removes them, and takes the maximum. (Returns `-Inf` with a warning if there is no unique maximum.)

Edited into an anonymous function per comment

# Answer
> 4 votes
# Python 2, 39 bytes

```
lambda l:max(1/l.count(n)*n for n in l)

```

Try it online!

# Answer
> 3 votes
# Ruby, 42 bytes

```
->x{(?0..?9).select{|r|x.count(r)==1}[-1]}

```

Try it online!

# Answer
> 3 votes
# C# (.NET Core), 27 97 86 58 57 75 bytes

```
using System.Linq;

n=>n.GroupBy(i=>i).Where(i=>i.Count()<2).Max(i=>i.Key)-48

```

Try it online!

Thanks @CarlosAlejo

# Answer
> 3 votes
# Bash \+ coreutils, ~~30~~ 28 bytes

-2 bytes thanks to Digital Trauma

```
fold -1|sort|uniq -u|tail -1

```

Try it online!

---

### Bash \+ coreutils, 20 bytes

```
sort|uniq -u|tail -1

```

Try it online!

If input is given as a list of digits, one per line, we can skip the fold stage. That feels like cheating though.

# Answer
> 3 votes
# \<\>\< (Fish), 93 bytes

```
0l1-l2-$:?v~~o;
v&]{[-3lr <   |.!01~$r&\
>r$1-:?!v$rl3-[{]:&:&=?^
@&::&:$~/|.!01 $}&~$?(

```

Try it in my interpreter

Found a fun bug in my interpreter testing this

Expects input pre-pushed to the stack

## Explanation

Top row: Setup. Push 0, the current maximum, l-1, the total number of iterations of the outer loop, and l-2, the total number of iterations in the inner loop. Initially both are the same.

Second row left: Shift left 1, then move the top item to the register. This is the candidate largest member.

Third row: Compare the register for each digit. If none match go down. Otherwise go up to second row right.

Second row right: Reset, then try another digit. This happens if the digit is equal to another.

Last row: We have found a unique digit! Now we check if it's better than the current max value, if so replace it. Then reset and jump to the start.

# Answer
> 2 votes
# APL (Dyalog), 14 bytes

-2 thanks toTwiNight.

```
⌈/⊢×1=(+/∘.=⍨)

```

`⌈/` the largest of

the arguments

`×` multiplied by

`1=(``)` the Boolean for each where one equals

`+/` the row sums of

`∘.=⍨` their equality table

Try it online!

# Answer
> 2 votes
# Japt `-h`, ~~12~~ ~~11~~ ~~10~~ 4 bytes

I/O as a digit array.

```
ü l1

```

Try it

# Answer
> 2 votes
## JavaScript (ES6), ~~52~~ 50 bytes

Takes input as a list of digits. Returns `0` if there are no unique digits.

```
s=>s.reduce((m,c)=>m>c|s.filter(x=>x==c)[1]?m:c,0)

```

### Test cases

```
let f =

s=>s.reduce((m,c)=>m>c|s.filter(x=>x==c)[1]?m:c,0)

console.log(f([1,2]))                 // 2
console.log(f([0]))                   // 0
console.log(f([4,8,5,9,0,2]))         // 9
console.log(f([4,9,5,9,0,2]))         // 5
console.log(f([9,9,9,9,9,9]))         // (0)
console.log(f([9,9,9,0,9,9]))         // 0
console.log(f([1,9,4,8,7,1,0,4,9,8])) // 7
```

# Answer
> 2 votes
# PHP, 40 bytes

```
<?=array_flip(count_chars($argn))[1]-48;

```

Try it online!

# PHP, 42 bytes

```
<?=chr(array_flip(count_chars($argn))[1]);

```

Try it online!

# Answer
> 2 votes
# Java (OpenJDK 8), ~~89~~ ~~85~~ 79 bytes

```
a->{int i=10,x[]=new int[i];for(int d:a)x[d]++;for(;i-->0&&x[i]!=1;);return i;}

```

Try it online!

-6 bytes thanks to @KevinCruijssen's insight!

# Answer
> 2 votes
# Java (JDK), 67 bytes

```
s->{int i=9;for(s=" "+s+" ";s.split(i+"").length!=2;i--);return i;}

```

Try it online!

# Answer
> 2 votes
# , ~~16~~ 12 bytes

```
0{\:~-.}./.~

```

Try it online!

# Answer
> 2 votes
**APL (NARS2000) 16 chars, 23(?) bytes**

```
{↑⌽⍸1=+⌿⍵∘.=⍳10}

```

(input as array of digits, e.g. {↑⌽⍸1=+⌿⍵∘.=⍳10}4 9 5 9 0 2)

# Answer
> 2 votes
# Desmos, 113 bytes

```
U(l)=max([min([\left\{l[n]=l[i]:-1,l[n]\right\} for i=join([0...n-1],[n+1...l.length+1])]) for n=[1...l.length]])

```

Takes input as a list.

Try it out and see versions that make slightly more sense

# Answer
> 2 votes
# *Acc!!*, 134 bytes

```
N
Count i while _%81/48 {
_+(1-_/3^(_%81-44)%3/2)*3^(_%81-44)-_%81+N
}
Count i while _ {
Count j while _/3^(13-i)%2 {
Write 57-i
0
}
}

```

Outputs a non-digit character if there are no unique digits. Try it online!

### Explanation

We partition the accumulator into two sections: `_%81` stores the most recently read character, while `_/81` stores ten counters, one for each digit, denoting whether that digit has occurred 0, 1, or 2+ times. For example, an accumulator value of 3214945 (20001100002001 in base 3) represents the following:

```
Occurrences of       Next character
9 8 7 6 5 4 3 2 1 0
-------------------  --------------
2 0 0 0 1 1 0 0 0 0  7 (character code 55, or 2001 in base 3)

```

When a digit occurs more than 2 times, we cap its occurrence count at 2. Then once all digits have been processed, the answer is the highest digit that has 1 as its occurrence count.

```
### Part 1: read the input and count digit occurrences ###

# Read the first character into the accumulator
N
# Loop while the most-recently-read character was a digit (>= charcode 48):
Count i while _%81/48 {
  # The digit we just read is _%81-48
  # Its occurrence count is _/81/3^(_%81-48)%3
  # We add 1 to the occurrence count; but if the occurrence count was already 2,
  # we also subtract 1, leaving it unchanged
  _+(1-_/81/3^(_%81-48)%3/2)*81*3^(_%81-48)
  # Clear out the previously read character and read a new character
  _-_%81+N
}

### Part 2: output the highest unique digit ###

# Count up i, starting at 0, until the accumulator gets zeroed out
Count i while _ {
  # 9-i is the current digit
  # Its occurrence count is _/81/3^(9-i)%3
  # Loop if the occurrence count is odd (i.e. 1, not 0 or 2):
  Count j while _/81/3^(9-i)%3%2 {
    # Output that digit
    Write (9-i)+48
    # Zero out the accumulator, causing both loops to end
    0
  }
}

```

If there are no unique digits, the `i` loop keeps going past `9`; some part of the newline character stored in `_%81` triggers the `j` loop, and a non-digit character is written out. (The golfed and ungolfed versions output different characters, and I haven't taken the trouble to analyze why, but it's guaranteed not to be a digit because `9-i` is less than 0 at this point.)

# Answer
> 1 votes
# F#, 88 bytes

```
let f i=Seq.countBy(fun a->a)i|>Seq.maxBy(fun a->if snd a>1 then 0 else int(fst a))|>fst

```

Try it online!

An improved approach from my first effort, results in less bytes.

*Points of interest: `fst` and `snd` return the first and second elements of a tuple respectively.*

# Answer
> 1 votes
# Mathematica, 42 bytes

```
Max@Position[RotateRight@DigitCount@#,1]-1&

```

# Answer
> 1 votes
# Jelly, 9 bytes

```
ṢŒrṪỊ$ÐfṀ

```

Try it online!

# Answer
> 1 votes
# Pyth, ~~8~~ ~~7~~ 6 bytes

1 byte thanks to isaacg.

1 byte thanks to FryAmTheEggman.

```
e{I#.g

```

Test suite.

# Answer
> 1 votes
# Pyth, 6 bytes

```
eS.m/Q

```

Test suite

Explanation:

```
eS.m/Q
eS.m/QbQ    Implicit variable introduction
  .m   Q    Find all minimal elements of the input by the following function:
    /Qb     Number of appearances in the input
eS          Take the maximum element remaining.

```

# Answer
> 1 votes
# Perl 5, 59 bytes

```
for$x(split//,<>){$d[$x]++};for($x=11;--$d[--$x];){}print$x

```

Try it online!

# Answer
> 1 votes
# Octave, 31 bytes

```
@(a)find(hist(a,0:9)==1)(end)-1

```

Try it online!

# Answer
> 1 votes
# Python 2, 41 bytes

```
lambda s:max(s,key=lambda o:s.count(o)<2)

```

Accepts input as string or list of strings

# Answer
> 1 votes
# Pyth -- 8 bytes

```
eSf!t/QT

```

And also

```
eS-Q.-Q{

```

Try it here and here

Explanation:

```
eSf!t/QT  # Takes string
  f       # Filter characters T of implicit input
     /QT  # by counting occurrences of that character in the input
   !t     # keeping only characters that occur once (i.e., !(# occurrences - 1)
 S        # Sort (puts them in ascending order
e         # Take the last (highest)

```

And

```
eS-Q.-Q{  # Takes list of digits
       {  # Deduplicate the list
    .-Q   # Take the original list, and remove each element in the deduplicated list once (so only duplicated digits are left)
  -Q      # Remove these duplicated digits from the list
eS        # As before, sort and take the last element

```

# Answer
> 1 votes
# Perl 6,  ~~33~~  25 bytes

```
{max keys .comb∖.comb.repeated}

```

input is either an Int or Str.

Test it

```
{max keys $_∖.repeated}

```

input is a list of digits.

Test it

## Expanded:

```
{ # bare block lambda with implicit parameter ｢$_｣

  max                  # the maximum from
    keys               # the keys (digits) out of the following Set

        $_             # the Input list of digits
      ∖                # Set minus (not ｢\｣)
        .repeated      # the repeated digits (implicit method call on ｢$_｣)
}

```

# Answer
> 1 votes
# APL (Dyalog), 11 bytes

```
⌈/{⍺×2-≢⍵}⌸

```

Try it online!

# Answer
> 1 votes
# Java, 70 bytes

Input is taken as a List of digits, as per question parameters.

```
n->n.stream().reduce(0,(p,q)->p>q||n.indexOf(q)!=n.lastIndexOf(q)?p:q)

```

The power of Streams in the palm of your hand!

The secret here is the beautiful `reduce` function. Starting with a 0, we walk through our list of digits and perform a retaining algorithm, keeping the one we've got (`?p:q`) if it's bigger than the new one (`p>q`) or if the new one isn't unique (`n.indexOf(q)!=n.lastIndexOf(q)`)

# Answer
> 1 votes
# Ruby, 42 bytes

Same byte count as the other Ruby answer, but different approach.

```
->x{x.chars.group_by{|d|x.count d}[1].max}

```

Crashes when there are no unique digits.

Try it online!

# Answer
> 1 votes
# x86 Machine Code (32-bit, requires built-in FPU), 35 bytes

```
C8 10 00 00 D9 EE DD 14 24 DD 5C 24 08 8B 01 FE 04 04
83 C1 04 4A 75 F5 6A 0A 58 48 FE 0C 04 75 FA C9 C3

```

The above code defines a function in 32-bit x86 machine code that finds the unique highest digit in an array of integer values. (The question says we can take the input as a "list of digits", and assembly language is like C in that it lacks a built-in list/array type, but rather represents them as a pointer and length. Therefore, the function is prototyped in C as follows:

```
int __fastcall FindHighestUniqueDigit(const int * ptrDigits, int count);

```

As the prototype suggests, this function is written to follow Microsoft's fastcall calling convention, which passes arguments in registers. The first parameter (`ptrDigits`) is passed in `ECX`, and the second argument (`count`) is passed in `EDX`. The return value is, as always, returned in `EAX`.

**Try it online!**

Here are the ungolfed assembly mnemonics:

```
FindHighestUniqueDigit:
   enter  16, 0                  ; reserve 16 bytes of space on the stack for a table
   fldz                          ; load 0 in the first x87 FPU register (st0)
   fst    QWORD PTR [esp+0]      ; store value in st0 on the stack, at offset 0
   fstp   QWORD PTR [esp+8]      ; store value in st0 on the stack, at offset 0, and pop st0
ReadDigits:
   mov    eax, DWORD PTR [ecx]   ; read next digit from array
   add    ecx, 4                 ; increment pointer to reference next digit (ints are 4-bytes long)
   inc    BYTE PTR [esp + eax]   ; increment value in table for this digit
   dec    edx                    ; decrement counter (length of array)
   jne    ReadDigits             ; keep looping as long as there are more digits to read
   push   10
   pop    eax                    ; space-efficient way to put '10' in EAX so we start with highest digit
ProcessDigits:
   dec    eax                    ; decrement EAX
   dec    BYTE PTR [esp + eax]   ; decrement value in table for this digit
   jnz    ProcessDigits          ; if that table value is now zero, we found a match; otherwise, keep looping
   leave                         ; undo effects of ENTER instruction
   ret                           ; return, with result in EAX (digit ID)

```

I suppose the code requires a bit of explanation…

Basically, what we do is create a table in memory, with enough space to store a unique count for each of the 9 possible digits (0 through 9).

```
| esp+0 | esp+1 | esp+2 | esp+3 | esp+4 | esp+5 | esp+6 | esp+7 | esp+8 | esp+9 | unused |
|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|--------|
|   9   |   8   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |   ??   |

```

The first `ENTER` instruction is responsible for allocating this space on the stack. We allocate 16 bytes because it's good practice to keep this a power of 2 for alignment purposes, 8 bytes isn't enough, and it doesn't hurt or cost anymore code bytes to allocate more than we need. The next three instructions are responsible for *zeroing* out all entries in this array. It's basically equivalent to `memset` in C, but shorter. We could have used the x86's `REP STOSD` string instruction, but that requires some setup (getting the right values in the right registers), and it turned out that (ab)using the x87 FPU to do 8-byte stores was shorter (required fewer bytes of code). All we do is load 0 at the top of the x87 FPU stack, which is pseudo-register `st0`. Then, we store that value across the first 8 bytes of the table, and finally, we store that value across the next 8 bytes of the table, popping it off of the x87 FPU stack at the same time.

The next section of the code is `ReadDigits`. This just iterates through the array of digits that we were passed, one digit at a time, and increments the unique counter for that digit in our table. You should be able to figure out exactly how this works by reading the comments for each of the instructions.

Finally, we come to the final phase, `ProcessDigits`. Actually, the `PUSH`+`POP` instructions right above this label are conceptually part of this phase, too. They just initialize `EAX` with 10 so that we'll start processing the table values for the *highest* possible digit, 9. Inside of the `ProcessDigits` loop, we eagerly decrement `EAX`, and then decrement the value in the table for the corresponding digit. If the resulting table value/counter is 0, then we've found our match, and we exit the loop. Otherwise, we keep looping and trying smaller digits. (Note that we could have done a comparison here—e.g., `cmp BYTE PTR [esp + eax], 1`+`jnz`—and in fact that's what we're *logically* doing, but the decrement was shorter to encode.)

Notice that if we never find a matching digit, then the code exhibits undefined behavior: it just keeps looping through memory, decrementing values and waiting until one is non-zero. When it finally finds one, it will terminate and return the ID, but the ID will be meaningless, and more importantly, it will have stomped all over the stack, decrementing values aimlessly!

The very last two instructions just clean up the stack (`LEAVE`) and return, with the return value (the highest unique digit that we found) left in `EAX`.

# Answer
> 1 votes
# CJam, 13 bytes

```
9A,sqfe=W%X#-

```

Try it Online

```
9    e# Push 9 to stack
A,s  e# Push "0123456789" to stack
q    e# Push input to stack ("1948710498")
fe=  e# Create array containing number of occurences of each digit in input number ([1,2,0,0,2,0,0,1,2,2])
W%   e# Reverse that array ([2,2,1,0,0,2,0,0,2,1])
X#   e# Get index of 1 in that array (2)
-    e# Calculate 9 - returned index to get highest unique digit (7)

```

# Answer
> 1 votes
# C# (Visual C# Interactive Compiler), 38 bytes

```
n=>n.Max(x=>n.Count(a=>a==x)<2?x:0)-48

```

Try it online!

# Answer
> 1 votes
# Julia 1.0, 41 bytes

```
s->maximum(c for c=s if count(==(c),s)<2)

```

Try it online!

# Answer
> 1 votes
# Wolfram Language (Mathematica), ~~43~~ ~~29~~ 28 bytes

```
Max@*Cases[{d_,1}->d]@*Tally

```

Try it online!

# Answer
> 1 votes
# Husk, 8 bytes

```
▲fȯ¬←LgO

```

Try it online!

Input is list of digits.

```
▲fȯ¬←LgO
▲           # maximum value of
 f          # filter list to retain only truthy values
      gO    # list: sort digits and group equal values together
  ȯ         # filter condition: combine functions:
    ←L      # length minus one (so length 1 = FALSE)
   ¬        # NOT (so length 1 = TRUE)

```

# Answer
> 1 votes
# Vyxal, 7 bytes

```
'?$Oṅ;G

```

Try it Online!

Takes input as a string.

### Explained

```
'?$Oṅ;G
'    ;  # From the input, keep only items where:
 ?$O    #   The count of the item in the input
    ṅ   #   Is <= 1
      G # Get the biggest digit from the remaining items.

```

# Answer
> 1 votes
# Arturo, ~~43~~ 32 bytes

```
$=>[tally&|select[k,v]->v=1|max]

```

Try it

# Answer
> 1 votes
# Scala, 100 bytes

Golfed version. Try it online!

```
def f(x:String)=Try(x.groupBy(identity).filter(_._2.length<2).keys.map(_.asDigit).max).getOrElse(-1)

```

Ungolfed vesrion. Try it online!

```
import scala.util.Try

object UniqueDigitMax {
  def main(args: Array[String]): Unit = {
    val f = (input: String) => Try(input.groupBy(identity).filter(_._2.length < 2).keys.map(_.asDigit).max).getOrElse(-1)

    println(f("1948710498"))  // 7
    println(f("485902"))      // 9
    println(f("0"))           // 0
    println(f("999099"))      // 0
    println(f("999999"))      // -1 (Undefined)
  }
}

```

# Answer
> 1 votes
# Kotlin, ~~106~~ 74 bytes

```
{n:List<Int>->n.groupingBy{it}.eachCount().filterValues{it==1}.keys.max()}

```

It's a real shame we never got `toDigits()`.

Takes input as a list of digits, errors if there are no unique digits.

Try it Online!

# Answer
> 1 votes
# Scala, 49 bytes

> The input can be taken as a single integer, a string, or a list of digits.

Golfed version. Try it online!

```
def f(s:String)=s.filter(c=>s.count(_==c)==1).max

```

Ungolfed version.

```
object Main {
  def f(s: String): Char = {
    s.filter(c => s.count(_ == c) == 1).max
  }

  def main(args: Array[String]): Unit = {
    println(f("1948710498"))
  }
}

```

# Answer
> 1 votes
# Java (JDK), 77 bytes

Not the best Java Stream solution, but a different approach.
Input is a String (because for obscure reasons `sum` and `max` aren't easily accessible in Streams of Lists of non-primitive integers).
Outputs `-48` in the "Anything" case.

```
s->s.chars().filter(e->s.chars().filter(c->c==e).sum()==e).max().orElse(0)-48

```

Try it online!

# Answer
> 1 votes
# Thunno 2 `G`, 3 bytes

```
cḅị

```

Input as a digit list.

#### Explanation

```
cḅị  # Implicit input
c    # Counts of each
 ḅ   # Equals one?
  ị  # Filter input by above
     # G flag gets maximum
     # Implicit output

```

#### Screenshot

# Answer
> 0 votes
## Clojure, 52 bytes

```
#(last(sort(for[c % :when(=((frequencies %)c)1)]c)))

```

Input is a string, returns a `char`, or `nil` if all digits are repeated.

# Answer
> 0 votes
# Actually, 16 bytes

```
╗1╤rR⌠$╜c⌡M1@í9-

```

Try it online!

# Answer
> 0 votes
# C (gcc), 76 bytes

```
d[58],i;main(){while((i=getchar())>0)++d[i];for(i=58;--d[--i];);putchar(i);}

```

Try it online!

# Answer
> 0 votes
# **PHP**, 79 76 bytes

Try it online!

```
foreach(array_count_values(str_split($n))as$x=>$i){$h=($i==1&&$x>$h)?$x:$h;}

```

Use with `$n = 495902;` it will print `5`.

# Answer
> 0 votes
# PowerShell v3+, 58 bytes

```
$i|% ToCharA*|sort|group|? count -lt 2|select -l 1 -exp N*

```

Assumes `$i` contains a string of digits.

Try it online!

# Answer
> 0 votes
# F#, 67 bytes

```
let f s=Seq.countBy id s|>Seq.filter(snd>>(=)1)|>Seq.maxBy fst|>fst

```

Try it online!

# Answer
> 0 votes
# Kotlin, 53 Bytes

```
val f={a:String->a.filter{a.count{b->it==b}<2}.max()}

```

Declares a lambda, `f` that takes in a string; same algorithm as the python answer. `it` is the implicit iterator of `a.filter`, and `b` is the explicitly declared iterator of `a.count` (because we can't use `it` again).

Try it online!

# Answer
> 0 votes
# Pip, 11 bytes

```
MX:_Na=1FIa

```

Takes input as a command-line argument. Try it online!

### Explanation

```
          a  1st cmdline arg
        FI   Filter digits by this function:
   _Na        Count of digit in a
      =1      equals 1 (i.e. keep only digits that appear exactly once)
MX:          Max of resulting list (using : to lower precedence)
             Autoprint (implicit)

```

# Answer
> 0 votes
## CJam, 15 bytes

```
r$e`{0=1=},e~W=

```

Explanation:

```
r    e# Read token:          "2515"
$    e# Sort:                "1255"
e`   e# Run-length encode:   [[1 '1] [1 '2] [2 '5]]
{    e# Filter where:
 0=  e#   The first element: [1 1 2]
 1=  e#   Equals one:        [1 1 0]
},   e# End filter:          [[1 '1] [1 '2]]
e~   e# Run-length decode:   "12"
W=   e# Last digit:          '2

```

# Answer
> 0 votes
# jq, 47 characters

(43 characters code + 4 characters command line options)

```
[./""|group_by(.)[]|select(length<2)[]]|max

```

Sample run:

```
bash-4.4$ jq -Rr '[./""|group_by(.)[]|select(length<2)[]]|max' <<< 1948710498
7

bash-4.4$ jq -Rr '[./""|group_by(.)[]|select(length<2)[]]|max' <<< 999999
null

```

Try on jq‣play

# Answer
> 0 votes
# Braingolf, 15 bytes

```
k&gG{!L1-?$_|}X

```

Try it online!

Takes input as a list of digits

## Explanation

```
k&gG{!L1-?$_|}X  Implicit input from commandline args
k                Sort in descending numerical order
 &g              Combine into single integer
   G             Split into digit runs
    {........}   Foreach loop..
     !L1-?       ..If length of item is greater than 1..
          $_     ....Remove item
            |    ..Endif
              X  Select highest value
                 Implicit output

```

To help visualize it a little, here's a run through showing the stack with input `122355567679`

```
k&gG{!L1-?$_|}X  [1,2,2,3,5,5,5,6,7,6,7,9]
k                [9,7,7,6,6,5,5,5,3,2,2,1]
 &g              [977665553221]
   G             [9,77,66,555,3,22,1]
    {!L1-?$_|}   [9,3,1]
              X  [9]

```

# Answer
> 0 votes
# k, 12 bytes

```
|/@&:1=#:'=:

```

Example:

```
k)F:|/@&:1=#:'=:
k)F "1948710498"
"7"
k)F "99999"
"\000"
k)F "mississippi"
"m"

```

The translation to `q` as explanation

```
max where 1 = count each group@

```

Interpreter available here

# Answer
> 0 votes
# , 19 bytes

```
[:>./(".*1=#)/.~@":

```

Explanation:

```
": converts the number to a string
@ propagates the result (composes the verbs)
/.~ classifies items of the list into partitions of identical items
". * 1=# - fork of 3 verbs:
   1=# - 1 if the key is unique, else 0
   ". converts the keys back to digits
   * multiplies the key values by 1 or 0 depending on their uniqueness
>./ finds the max digit
[: caps the fork, since we have 2 verbs only for the key operator

```

Example:

```
   a=.123456547
     ": a
    123456547  NB. string
    </.~@": a
    ┌─┬─┬─┬──┬──┬─┬─┐
    │1│2│3│44│55│6│7│          NB. keys
    └─┴─┴─┴──┴──┴─┴─┘

(1=#)/.~@": a
1 1 1 0 0 1 1                  NB. mask for unique digits

(".*1=#)/.~@": a
1 2 3 0 0 6 7                  NB. digits multiplied by the mask, rendering
                                   duplicates to 0

([:>./(".*1=#)/.~@":) a        NB. finds the max nonrepeating digit
7

```

Try it online!

# Answer
> 0 votes
# Perl 5 `-pF`, 36 bytes

```
$_=join'',sort@F;s/(.)\1+//g;$_=chop

```

Try it online!

# Answer
> 0 votes
# Stax, 4 bytes

```
|!|M

```

Run and debug it

This program takes an array of digits. It works by calculating the maximum "anti-mode". I'm not sure if anti-mode is a real thing outside of stax, but it refers to the rarest element in list.

# Answer
> 0 votes
# dc, 48 bytes

```
[1+dd;a+r:az0<A]dsAx[d]sD1[dd;a=D1+dB>M]dsMxr1-p

```

Try it online!

Takes input as digits entered on the stack. I'm assuming this is a fair stand-in for a list of digits, since the justification for that was that folks were just dropping in boilerplate to turn an integer into a list of digits, and the task would be the same here (just... as a stack). Returns '10' on an entry w/ no unique digits.

Macro `A` builds an array `a` by taking each digit, loading the value in its own index (this will be 0 if thus far unassigned), adding itself, and storing this new value. We actually have to add 1 to every digit first so that 0 works correctly, and at the end we subtract 1 from our final result to make up for this. Ignoring that briefly for illustrative purposes, any index (let's call it *n*) of `a` will now have one of the following: 0 if *n* didn't exist as a digit in our original number, *n* itself if *n* was unique, or some multiple of *n* other than *n*\*1 if *n* existed and was not unique.

In `dc`, conditionals either run a macro if true or do nothing if false, so you *need* a macro for them to do anything. `[d]sD` is a macro, `D` that simply duplicates a value.

A 1 goes on the stack to act as a counter of sorts, and then macro `M` runs. `M` really just takes this counter number, loads that index from `a`, compares it to itself, and duplicates itself (by running `D`) if they're equal. So, if they aren't equal (digit didn't exist or wasn't unique), we're simply left with one instance of our counter; if they *are* equal, we now have another copy of it on the stack. Increment, and keep on going 1-10. When this is done, we swap the top two values on the stack and subtract one as mentioned earlier.

# Answer
> 0 votes
# Jelly, 7 bytes

```
ċⱮ`Ị×⁸Ṁ

```

Try it online!

Input as a list of digits

## How it works

```
ċⱮ`Ị×⁸Ṁ - Main link. Takes the list D on the left
  `     - Using D as both arguments:
 Ɱ      -   For each element in D:
ċ       -     Count occurrences in D
   Ị    - Insignificant; Yield 1 if abs(x) ≤ 1 else 0
     ⁸  - Yield D
    ×   - Multiply the digits by the insignificants
      Ṁ - Take the maximum

```

# Answer
> 0 votes
# Factor, 27 bytes

```
[ non-repeating ?supremum ]

```

Attempt This Online!

* `non-repeating` Get only the elements of a sequence that don't repeat.
* `?supremum` Get the largest element of a sequence, or return `f` for the empty sequence.

---
Tags: code-golf, number, integer
---


title: Ragged Matrix Indexing

text:
# Question
Title: Ragged Matrix Indexing
A ragged matrix, is a matrix that has a different number of elements in each row. Your challenge is to write a program in any favorable language to find the indices of all occurrences of target in the ragged matrix.

# Input:

A list of ragged lists (can be empty) of positive integers and a target range e.g. `26-56`. The target range, given 2 positive integers. For languages that do not support this type of list, you can input it as a string representation

You may assume that `a<=b`

# Output:

If a number in the ragged list is within the range or equal to `a` or equal to `b`, output the index of the ragged list then the index of the number in that ragged list e.g. `0 4` \- The `0` is the first ragged list in the input and the `4` is the index of the number in the first ragged list

# Test cases:

```
[[[1,3,2,32,19],[19,2,48,19],[],[9,35,4],[3,19]],19-53]
->
[[0,3],[0,4],[1,0],[1,2],[1,3],[3,1],[4,1]]

[[[1,2,3,2],[],[7,9,2,1,4]],2-2]
->
[[0,1],[0,3],[2,2]]

```

You can choose to follow the output format above or output it in the following as well:

```
[[[1,3,2,32,19],[19,2,48,19],[],[9,35,4],[3,19]],19-53]
->
0 3 0 4 1 0 1 2 1 3 3 1 4 1

```

0-based and 1-based indexing is allowed

You can output your answers in any way as long as it is distinguishable what the indexes of the number and matrix are

You may assume the integers in the list are always positive and non-zero

This is code-golf, so shortest code wins!

# Answer
# Jelly, ~~8~~ 7 bytes

```
r/iⱮⱮŒṪ

```

Try it online!

## Walkthrough

```
 /        Reduce input range list by
r         range
   ⱮⱮ     Foreach at depth 2
              (on the right argument)
  i           Find first index of RHS in LHS
              (Or, in this case, checks whether
               current item (RHS) is within range (LHS)? )
      ŒṪ  All truthy multidimensional indices

```
> 5 votes

# Answer
# Wolfram Language (Mathematica), 23 bytes

```
Position[a_/;#<=a<=#2]&

```

Try it online!

Input `[a, b][list]`. Returns 1-indexed.
> 6 votes

# Answer
# APL (Dyalog Extended), 8 bytes

Full program. Prompts for range, then array.

```
⍸↑⎕∊¨…/⎕

```

Try it online!

Explained from the right:

prompt (for range)

`…/` reduce using the range function (gives enclosed list of all number in the range)

`∊¨` check if the elements of each of the following lists are in the entire (because it is enclosed) range:

prompt for array

mix list of Boolean lists into a matrix, padding with Falses

indices of Trues
> 5 votes

# Answer
# , 87 bytes

Or **\>=4.1, 80 bytes** by replacing the word `function` with a `\`.

```
function(l,a,b,`[`=lapply)cbind(rep(seq(l),lengths(w<-l[`%in%`,a:b][which])),unlist(w))

```

Try it online!

---

Solution shorter in \>=4.1:

### , 92 bytes

Or **\>=4.1, 78 bytes** by replacing two `function` occurrences with `\`s.

```
function(l,a,b)cbind(rep(seq(l),lengths(w<-lapply(l,function(x)which(x%in%a:b)))),unlist(w))

```

Try it online!

---

Outgolfed by @Giuseppe. See that answer for a detailed explanation and comparison of our approaches.
> 5 votes

# Answer
# Python 3, 69 bytes

```
lambda l,r,e=enumerate:[[X,Y]for X,x in e(l)for Y,y in e(x)if y in r]

```

Try it online!

-3 thanks to @tsh
> 4 votes

# Answer
# 05AB1E, 13 (or 7?) bytes

```
εNUεIŸsåiXN‚?

```

First input is the matrix; second the range as pair of integers.
Outputs pairs of 0-based indices without delimiter to STDOUT.

Try it online or verify all test cases.

Not sure if this is a valid output-format:

```
ŸIåεƶ0K

```

First input is the range as pair of integers; second the matrix.
Outputs the 1-based truthy indices of each row.

Try it online or verify all test cases.

**Explanation:**

```
ε           # Map over each row of the (implicit) first input-matrix:
 NU         #  Store the row-index in variable `X`
 ε          #  Map over each integer in the row:
  I         #   Push the second (implicit) input-pair
   Ÿ        #   Convert it to an inclusive ranged list
    såi     #   If the current integer is in this list:
       XN‚  #    Pair `X` with the inner map-index
          ? #    Pop and output it

Ÿ           # Convert the (implicit) first input-pair to an inclusive ranged list
 I          # Push the second input-matrix
  å         # Check for each inner-most value if it's within this range
   ε        # Map over these integers:
    ƶ       #  Multiply each value by its 1-based index
     0K     #  Remove all 0s
            # (after which the list of lists is output implicitly)

```
> 3 votes

# Answer
# K (ngn/k), 13 bytes

```
{+&~(y+!2)'x}

```

Try it online!

Takes the ragged matrix as `x` (first arg, a list of lists) and the range as `y` (second arg, a pair of integers).

* `(y+!2)` convert the range from e.g. `19 53` to `19 54` (to do a `[lb;ub]` comparison rather than `[lb;ub)`)
* `(...)'x` do a binary lookup of `x` in the list generated by `(...)`. if a value in `x` is between the (adjusted) indices, `0` is returned
* `~` not the above; values within the range become `1` and all others `0`
* `&` use "deep-where" to return indices of 1's
* `+` transpose the result

It's likely that the final `+` (transpose) can be elided depending on what constitutes acceptable output.
> 3 votes

# Answer
# , 78 bytes

```
function(l,a,b)cbind(rep(seq(l),L<-lengths(l)),sequence(L))[unlist(l)%in%a:b,]

```

Try it online!

Originally posted as a comment on pajonk's answer, so uses that test harness. That answer is a very natural way to approach the problem in R, so if I hadn't peeked first, I probably wouldn't have found this gem.

Using R-style indexing, a single value in `l` is `l[[i]][j]`, i.e., the `j`th (vector) element of the `i`th element of the list `l`. pajonk's answer generates a list of all the indices `j` for each `i` such that `l[[i]][j] %in% a:b` and then joins them with an appropriately-sized list of `i`, as below:

```
function(l,a,b){
in_ab <- sapply(l,`%in%`,a:b)		# for each element of l, return TRUE/FALSE where elements are in a..b
j_idx_list <- sapply(in_ab,which)	# now return the 1-based indices of the TRUE values
j_idx <- unlist(j_idx_list)		# and collapse into a single vector
i_lengths <- lengths(j_idx_list)	# take the # of valid j-indices in each sublist
i_idx <- rep(seq(l),i_lengths)		# and generate i-indices to match
cbind(i_idx,j_idx)			# and combine
}

```

This answer instead uses some functions rarely used in golfing, `sequence` and `lengths` to generate all the valid pairs `i,j` and then filters them directly. In fact, `sequence` is such an odd function in R that the docs used to say1 that "it mainly exists in reverence to the very early history of R", as I have mentioned before.

Ungolfed a bit:

```
function(l,a,b){
L <- lengths(l)			# find the lengths of each element of l
j_idx <- sequence(L)		# for each Length h, generate 1..h and append them together in order
i_idx <- rep(seq(l),L)		# replicate each of 1..length(l) times equal to the length of l[[i]]
filter_idx <- unlist(l)%in%a:b	# index for filtering
cbind(i_idx,j_idx)[filter_idx,]	# combine i,j indices as columns of a matrix, and filter the rows
}

```

1 Starting in version 4.0.0, `sequence` was updated to accept a `from` and `by` argument, much like `seq`, and this line was removed.
> 3 votes

# Answer
# Charcoal, 34 bytes

```
≔⮌Ｉ⪪η-η≔…·⊟η⊟ηηＦＬθＦ⌕ＡＥ§θι№ηκ¹Ｉ⟦⟦ικ

```

Try it online! Link is to verbose version of code. Explanation:

```
≔⮌Ｉ⪪η-η≔…·⊟η⊟ηη

```

Convert the second input into a range.

```
ＦＬθ

```

Loop over the sublists.

```
Ｆ⌕ＡＥ§θι№ηκ¹

```

Loop over the indices where the element lies within the range.

```
Ｉ⟦⟦ικ

```

Output the outer and inner indices on separate lines double-spaced between each pair of indices.
> 2 votes

# Answer
# JavaScript (V8), ~~58~~ 56 bytes

```
(a,l,r)=>a.map((x,i)=>x.map((y,j)=>l>y|y>r||print(i,j)))

```

Try it online!

*Saved 2 bytes thanks to Arnauld.*
> 2 votes

# Answer
# Factor, 71 bytes

```
[ '[ [ _ _ between? ] arg-where ] map <enumerated> expand-values-push ]

```

## Explanation

* `'[ [ _ _ between? ] arg-where ] map` Map the indices inside the range to each row of the ragged matrix.
* `<enumerated>` Zip a list with its indices.
* `expand-values-push` Combine each key with each of the elements in its value, collecting the results in a single list of pairs.

```
                                     ! { { 1 3 2 32 19 } { 19 2 48 19 } { } { 9 34 4 } { 3 19 } } 19 53
'[ [ _ _ between? ] arg-where ] map  ! { V{ 3 4 } V{ 0 2 3 } V{ } V{ 1 } V{ 1 } }
<enumerated>                         ! { { 0 V{ 3 4 } } { 1 V{ 0 2 3 } } { 2 V{ } } { 3 V{ 1 } } { 4 V{ 1 } } }
expand-values-push                   ! V{ { 0 3 } { 0 4 } { 1 0 } { 1 2 } { 1 3 } { 3 1 } { 4 1 } }

```
> 2 votes

# Answer
# Vyxal, 12 bytes

```
ṫ÷r£hƛ¥vc;ÞT

```

Try it Online!

Needs input in form: `[<main_arr>, [a, b]]`

```
ṫ            # Get [a, b]
 ÷r          # Get range a..b
   £         # Set to register
    h        # Main array
     ƛ       # Begin map
      ¥      # Push register
       vc    # Is item inside range (vectorized)
         ;ÞT # Close map and print truthy indices

```
> 2 votes

# Answer
# Python3, 80 bytes

```
lambda l,a,b:[ [X,Y] for X,x in enumerate(l) for Y,y in enumerate(x) if a<=y<=b]

```

Try it online!
> 1 votes

# Answer
# Scala, 112 bytes

for a 2d matrix, find all indices where element is between the Range.

---

Golfed version. Try it online!

```
def f(l:Seq[Seq[Int]],r:Range)={for{(x,i)<-l.zipWithIndex;(y,j)<-x.zipWithIndex if r.contains(y)}yield Seq(i,j)}

```

Ungolfed version. Try it online!

```
object PythonToScala {
  def main(args: Array[String]): Unit = {
    val l: List[List[Int]] = List(List(1, 3, 2, 32, 19), List(19, 2, 48, 19), List(), List(9, 35, 4), List(3, 19))
    val a: Int = 19
    val b: Int = 53

    def f(l: List[List[Int]], r: Range): List[List[Int]] = {
      for {
        (x, i) <- l.zipWithIndex
        (y, j) <- x.zipWithIndex if r.contains(y)
      } yield List(i, j)
    }

    println(f(l, a until b))
  }
}

```
> 1 votes

---
Tags: code-golf, matrix, ragged-list
---