Odd words

From Rosetta Code
Odd words is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Given a list of words, (use the words from the dictionary unixdict.txt).

Take the letters at odd indices letters from each word. If the result is present in the list, then display the result. The length of the odd word should be >   4.


Other tasks related to string operations:
Metrics
Counting
Remove/replace
Anagrams/Derangements/shuffling
Find/Search/Determine
Formatting
Song lyrics/poems/Mad Libs/phrases
Tokenize
Sequences



11l

Translation of: Python
V wordSet = Set(File(‘unixdict.txt’).read().split("\n"))

Set[String] oddWordSet

L(word) wordSet
   I word.len >= 9 & word[(0..).step(2)] C wordSet
      oddWordSet.add(word[(0..).step(2)])

L(i) sorted(Array(oddWordSet))
   print(i)
Output:
brain
cider
cried
grata
hades
plain
point
saute
sight
slain
spree
trial

AArch64 Assembly

Works with: as version Raspberry Pi 3B version Buster 64 bits
or android 64 bits with application Termux
/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program oddwords64.s   */
 
/************************************/
/* Constantes                       */
/************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc" 
.equ BUFFERSIZE, 300000
.equ WORDSIZE,   4

//.include "../../ficmacros64.inc"        // use for developper debugging
/*******************************************/
/* Structures                          **/
/*******************************************/
/* structure words array  */
    .struct  0
st_word_adr:
    .struct st_word_adr + 8
st_word_size:
    .struct st_word_size + 8
st_word_end:  
/************************************/
/* Initialized data                 */
/************************************/
.data
szMessOpen:           .asciz "File open error.\n"
szMessRead:           .asciz "File read error.\n"
szMessClose:          .asciz "File close error.\n"
szFileName:           .asciz "unixdict.txt"
szMessResult:         .asciz " : "
szCarriageReturn:     .asciz "\n"
szMessStart:          .asciz "Program 64 bits start.\n"
/************************************/
/* UnInitialized data               */
/************************************/
.bss 
sZoneConv:            .skip 24
sBuffer:              .skip BUFFERSIZE     // file buffer
.align 4
WordArray:            .skip st_word_end * 0x10000
/************************************/
/*  code section                    */
/************************************/
.text
.global main   
main:                        // entry of program
    ldr x0,qAdrszMessStart
    bl affichageMess
    ldr x0,qAdrszFileName    // file name
    ldr x1,qAdrsBuffer       // read buffer address
    ldr x2,#iBufferSize      // buffer size
    ldr x3,qAdrWordArray     // word address array
    bl readFile
    cmp x0,#-1               // file error ?
    beq 100f
    mov x2,x0                // word counter
    ldr x0,qAdrsBuffer
    ldr x1,qAdrWordArray     // array address
    bl traitWord

100:                         // standard end of the program
    mov x0, #0               // return code
    mov x8, #EXIT            // request to exit program
    svc 0                    // perform the system call

qAdrsZoneConv:            .quad  sZoneConv
qAdrszMessResult:         .quad  szMessResult
qAdrszCarriageReturn:     .quad  szCarriageReturn
qAdrszMessStart:          .quad  szMessStart
qAdrszFileName:           .quad  szFileName
qAdrszMessOpen:           .quad  szMessOpen
qAdrszMessRead:           .quad  szMessRead
qAdrszMessClose:          .quad  szMessClose
qAdrsBuffer:              .quad  sBuffer
iBufferSize:              .quad  BUFFERSIZE
qAdrWordArray:            .quad  WordArray
/***************************************************/
/*   read file and create array words                   */
/***************************************************/
/* x0 contains file name */
/* x1 contains a file buffer */
/* x2 contains buffer size */
/* x3 contains array word address */
readFile:
    stp x1,lr,[sp,-16]!
    stp x2,x3,[sp,-16]! 
    stp x4,x5,[sp,-16]! 
    stp x6,x7,[sp,-16]! 
    stp x8,x9,[sp,-16]! 
    mov x9,x1                // file buffer
    mov x6,x2
    mov x1,x0
    mov x10,x3
    mov x0,AT_FDCWD
    mov x2,#O_RDWR           // flags
    mov x3,#0                // mode 
    mov x8,#OPEN             // file open
    svc 0 
    cmp x0,#0                // error ?
    ble 99f
    mov x7,x0                // FD save

    mov x0,x7
    mov x1,x9                // read buffer address
    mov x2,x6
    mov x8,#READ             // call system read file
    svc 0 
    cmp x0,#0                // error read ?
    blt 97f
    mov x6,x0                // save file size
    mov x0,x7                // FD
    mov x8,#CLOSE            // call system close file
    svc 0 
    cmp x0,#0                // error close ?
    blt 96f    
    mov x1,#0                // index buffer
    mov x2,x9                // file buffer address
    mov x3,#0                // word length
    mov x5,#0                // word counter
1:
    ldrb w4,[x9,x1]          // load character file buffer
    cmp x4,#0x0D             // end word ?
    beq 2f                   // yes
    add x1,x1,#1             // increment index and length
    add x3,x3,#1
    b 1b                     // and loop
2:              // 
    strb wzr,[x9,x1]          // store 0 final in word
    cmp x3,#WORDSIZE         // word length  ?
    ble 3f                   // no ?
    mov x0,#st_word_end      // structure size
    madd x0,x5,x0,x10        // compute word item address 
    str x2,[x0,#st_word_adr] // store word address in array word
    str x3,[x0,#st_word_size] // store word size in array word
    add x5,x5,#1             // increment word counter
3:
    add x1,x1,#2             // increment index buffer (0D0A) 
    cmp x1,x6                // end ?
    bge 4f
    add x2,x9,x1             // new word begin
    mov x3,#0                // init word length
    b 1b                     // and loop   
4:
    mov x0,x5                // return word counter 
    b 100f
96:                          // display error messages
    ldr x0,qAdrszMessClose
    bl affichageMess     
    mov x0,#-1               // error
    b 100f
97:
    ldr x0,qAdrszMessRead
    bl affichageMess 
    mov x0,#-1               // error
    b 100f
99:
    ldr x0,qAdrszMessOpen
    bl  affichageMess    
    mov x0,#-1               // error

 100:
    ldp x8,x9,[sp],16
    ldp x6,x7,[sp],16
    ldp x4,x5,[sp],16
    ldp x2,x3,[sp],16
    ldp x1,lr,[sp],16
    ret 
/***************************************************/
/*   word analyse                                  */
/***************************************************/
/* x0 contains a file buffer */
/* x1 contains array word address */
/* x2 contains array element */
traitWord:
    stp x1,lr,[sp,-16]!
    stp x2,x3,[sp,-16]!
    stp x4,x5,[sp,-16]! 
    stp x6,x7,[sp,-16]! 
    stp x8,x9,[sp,-16]! 
    stp x10,x12,[sp,-16]! 
    mov x7,x0               // save buffer address
    mov x8,x1               // save array word address
    mov x9,x2               // save size
    mov x10,#0              // init index word array
    sub sp,sp,#80           // reserve 80 byte on stack for work array
    mov fp,sp               // work array address
1:
    mov x0,#st_word_end     // structure size
    madd x0,x10,x0,x8       // compute word item address 
    ldr x12,[x0,#st_word_adr]  // load one word address
    ldr x5,[x0,#st_word_size]  // load word size   
    mov x3,#0               // index word
    mov x6,#0               // size new word 
2:
    ldrb w4,[x12,x3]        // load characters on odd index
    strb w4,[fp,x6]         // store in wprk array on stack
    add x6,x6,#1            // increment size new word
    add x3,x3,#2            // increment index
    cmp x3,x5               // end word ?
    ble 2b
    cmp x6,#WORDSIZE        // length new word ok ?
    ble 10f
    strb wzr,[fp,x6]        // store 0 final new word
                            // search new word in word array by binary search
                            // in french recherche dichotomique
    mov x3,#0               // low index
    sub x4,x9,#1            // high index = number of elements - 1
3:                          // begin search loop
    cmp x3,x4               // low > high
    bgt 10f                 // not found
    add x7,x3,x4            // compute (low + high) /2
    lsr x7,x7,#1
    mov x1,#st_word_end     // structure size
    madd x2,x7,x1,x8         // compute word item address 
    ldr x0,[x2,#st_word_adr]  // load word array address at new index r7                   
    mov x1,fp               // search word address
    bl comparerChaines      // alpha comparison
    cmp x0,#0
    beq 4f                  // find 
    add x0,x7,1
    csel x3,x0,x3,lt        // lower -> index low = index + 1
    sub x0,x7,1
    csel x4,x0,x4,gt        // bigger -> index high = index - 1
    b 3b                    // and loop
    
4:                          // ok -> display result
    mov x0,x12
    bl affichageMess
    ldr x0,qAdrszMessResult
    bl affichageMess
    mov x0,fp
    bl affichageMess
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    
10:    
    mov x6,#0                // init new length new word
    add x10,x10,#1           // increment index word array
    cmp x10,x9               // end ?
    blt 1b                   // no -> loop
    
100:
    add sp,sp,#80            // stack alignement release work array
    ldp x10,x12,[sp],16    
    ldp x8,x9,[sp],16
    ldp x6,x7,[sp],16
    ldp x4,x5,[sp],16
    ldp x2,x3,[sp],16
    ldp x1,lr,[sp],16
    ret 

/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeARM64.inc"
Output:
Program 64 bits start.
barbarian : brain
childbear : cider
corrigenda : cried
gargantuan : grata
headdress : hades
palladian : plain
propionate : point
salvation : slain
siltation : slain
slingshot : sight
statuette : saute
supersede : spree
supervene : spree
terminable : trial

Ada

Using instances of generic procedure to filter odd/even words.

with Ada.Text_Io;
with Ada.Containers.Indefinite_Ordered_Maps;

procedure Odd_Words is
   use Ada.Text_Io;

   package String_Maps is
     new Ada.Containers.Indefinite_Ordered_Maps (Key_Type     => String,
                                                 Element_Type => String);

   Filename : constant String := "unixdict.txt";
   Words    : String_Maps.Map;

   function Get_Odd (Word : String) return String is
      Odd : String (1 .. (Word'Length + 1) / 2);
   begin
      for Index in Odd'Range loop
         Odd (Index) := Word (1 + 2 * (Index - 1));
      end loop;
      return Odd;
   end Get_Odd;

   function Get_Even (Word : String) return String is
      Even : String (1 .. Word'Length / 2);
   begin
      for Index in Even'Range loop
         Even (Index) := Word (1 + 1 + 2 * (Index - 1));
      end loop;
      return Even;
   end Get_Even;

   generic
      with function Filter (Word : String) return String;
   procedure Iterate_Map;

   procedure Iterate_Map is
   begin
      for Word of Words loop
         declare
            Half : constant String := Filter (Word);
         begin
            if Half'Length > 4 and then Words.Contains (Half) then
               Put (Word); Set_Col (15); Put_Line (Half);
            end if;
         end;
      end loop;
   end Iterate_Map;

   procedure Put_Odd_Words  is new Iterate_Map (Get_Odd);
   procedure Put_Even_Words is new Iterate_Map (Get_Even);

   File : File_Type;
begin
   Open (File, In_File, Filename);
   while not End_Of_File (File) loop
      declare
         Word : constant String := Get_Line (File);
      begin
         Words.Insert (Word, Word);
      end;
   end loop;
   Close (File);

   Put_Line ("Odd words:");
   Put_Odd_Words;
   New_Line;

   Put_Line ("Even words:");
   Put_Even_Words;
end Odd_Words;
Output:
Odd words:
barbarian     brain
childbear     cider
corrigenda    cried
gargantuan    grata
headdress     hades
palladian     plain
propionate    point
salvation     slain
siltation     slain
slingshot     sight
statuette     saute
supersede     spree
supervene     spree
terminable    trial

Even words:
cannonball    annal
importation   motto
psychopomp    scoop
starvation    train
upholstery    posey

ALGOL 68

Works with: ALGOL 68G version Any - tested with release 2.8.3.win32

Based on (and almost identical to) the Alternade Words sample.

# find words where the odd letters also form a word                  #
# use the associative array in the Associate array/iteration task    #
PR read "aArray.a68" PR
IF  FILE input file;
    STRING file name = "unixdict.txt";
    open( input file, file name, stand in channel ) /= 0
THEN
    # failed to open the file                                        #
    print( ( "Unable to open """ + file name + """", newline ) )
ELSE
    # file opened OK                                                 #
    BOOL at eof := FALSE;
    # set the EOF handler for the file #
    on logical file end( input file, ( REF FILE f )BOOL:
                                     BEGIN
                                         # note that we reached EOF on the #
                                         # latest read #
                                         at eof := TRUE;
                                         # return TRUE so processing can continue #
                                         TRUE
                                     END
                       );
    # returns w split into n parts by taking alternate characters    #
    PRIO SPLIT = 1;
    OP   SPLIT = ( STRING w, INT n )[]STRING:
         BEGIN
            [ n ]STRING result;
            FOR r pos FROM LWB result TO UPB result DO result[ r pos ] := "" OD;
            INT r pos := 1;
            FOR w pos FROM LWB w TO UPB w DO
                result[ r pos ] +:= w[ w pos ];
                r pos +:= 1;
                IF r pos > n THEN r pos := 1 FI
            OD;
            result
         END; # SPLIT #
    # build an associative array of the words                        #
    REF AARRAY words := INIT LOC AARRAY;
    WHILE STRING word;
          get( input file, ( word, newline ) );
          NOT at eof
    DO
        words // word := word
    OD;
    close( input file );
    # find the words where the odd letters form a word at least five #
    # characters long, the word itself must therefore be at least    #
    # nine characters long                                           #
    REF AAELEMENT e := FIRST words;
    WHILE e ISNT nil element DO
        IF STRING word = key OF e;
           INT w len = ( UPB word + 1 ) - LWB word;
           w len >= 9
        THEN
            []STRING sub word = word SPLIT 2;
            IF words CONTAINSKEY sub word[ 1 ]
            THEN
                print( ( word, ": " ) );
                FROM w len + 1 TO 18 DO print( ( " " ) ) OD;
                print( ( sub word[ 1 ], newline ) )
            FI
        FI;
        e := NEXT words
    OD
FI
Output:

As with the Alternade Words Algol 68 sample, the output is not sorted, it has been sorted here for ease of comparison with the other samples' output.

barbarian:          brain
childbear:          cider
corrigenda:         cried
gargantuan:         grata
headdress:          hades
palladian:          plain
propionate:         point
salvation:          slain
siltation:          slain
slingshot:          sight
statuette:          saute
supersede:          spree
supervene:          spree
terminable:         trial

ARM Assembly

Works with: as version Raspberry Pi
or android 32 bits with application Termux
/* ARM assembly Raspberry PI  */
/*  program oddwords.s   */
 
/************************************/
/* Constantes                       */
/************************************/
/* for this file see task include a file in language ARM assembly*/
.include "../constantes.inc"
.equ READ,   3
.equ WRITE,  4
.equ OPEN,   5
.equ CLOSE,  6
.equ O_RDWR,  0x0002         @ open for reading and writing
.equ BUFFERSIZE, 300000
.equ WORDSIZE,   4

//.include "../../ficmacros32.inc"        @ use for developper debugging
/*******************************************/
/* Structures                          **/
/*******************************************/
/* structure words array  */
    .struct  0
st_word_adr:
    .struct st_word_adr + 4
st_word_size:
    .struct st_word_size + 4
st_word_end:  
/************************************/
/* Initialized data                 */
/************************************/
.data
szMessOpen:           .asciz "File open error.\n"
szMessRead:           .asciz "File read error.\n"
szMessClose:          .asciz "File close error.\n"
szFileName:           .asciz "unixdict.txt"
szMessResult:         .asciz " : "
szCarriageReturn:     .asciz "\n"
szMessStart:          .asciz "Program 32 bits start.\n"
/************************************/
/* UnInitialized data               */
/************************************/
.bss 
sZoneConv:            .skip 24
sBuffer:              .skip BUFFERSIZE     @ file buffer
.align 4
WordArray:            .skip st_word_end * 0x10000
/************************************/
/*  code section                    */
/************************************/
.text
.global main   
main:                        @ entry of program
    ldr r0,iAdrszMessStart
    bl affichageMess
    ldr r0,iAdrszFileName    @ file name
    ldr r1,iAdrsBuffer       @ read buffer address
    ldr r2,#iBufferSize      @ buffer size
    ldr r3,iAdrWordArray     @ word address array
    bl readFile
    cmp r0,#-1               @ file error ?
    beq 100f
    mov r2,r0                @ word counter
    ldr r0,iAdrsBuffer
    ldr r1,iAdrWordArray     @ array address
    bl traitWord

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

iAdrsZoneConv:            .int sZoneConv
iAdrszMessResult:         .int szMessResult
iAdrszCarriageReturn:     .int szCarriageReturn
iAdrszMessStart:          .int szMessStart
iAdrszFileName:           .int szFileName
iAdrszMessOpen:           .int szMessOpen
iAdrszMessRead:           .int szMessRead
iAdrszMessClose:          .int szMessClose
iAdrsBuffer:              .int sBuffer
iBufferSize:              .int BUFFERSIZE
iAdrWordArray:            .int WordArray
/***************************************************/
/*   read file and create array words                   */
/***************************************************/
/* r0 contains file name */
/* r1 contains a file buffer */
/* r2 contains buffer size */
/* r3 contains array word address */
readFile:
    push {r1-r9,lr}          @ save registers
    mov r9,r1                @ file buffer
    mov r6,r2
    mov r10,r3
    mov r1,#O_RDWR           @ flags
    mov r2,#0                @ mode 
    mov r7,#OPEN             @ file open
    svc 0 
    cmp r0,#0                @ error ?
    ble 99f
    mov r8,r0                @ FD save

    mov r0,r8
    mov r1,r9                @ read buffer address
    mov r2,r6
    mov r7,#READ             @ call system read file
    svc 0 
    cmp r0,#0                @ error read ?
    blt 97f
    mov r6,r0                @ save file size
    mov r0,r8                @ FD
    mov r7,#CLOSE            @ call system close file
    svc 0 
    cmp r0,#0                @ error close ?
    blt 96f    
    mov r1,#0                @ index buffer
    mov r2,r9                @ file buffer address
    mov r3,#0                @ word length
    mov r5,#0                @ word counter
1:
    ldrb r4,[r9,r1]          @ load character file buffer
    cmp r4,#0x0D             @ end word ?
    beq 2f                   @ yes
    add r1,r1,#1             @ increment index and length
    add r3,r3,#1
    b 1b                     @ and loop
2:
    mov r4,#0                @ 
    strb r4,[r9,r1]          @ store 0 final in word
    cmp r3,#WORDSIZE         @ word length  ?
    ble 3f                   @ no ?
    mov r0,#st_word_end      @ structure size
    mla r0,r5,r0,r10         @ compute word item address 
    str r2,[r0,#st_word_adr] @ store word address in array word
    str r3,[r0,#st_word_size] @ store word size in array word
    add r5,r5,#1             @ increment word counter
3:
    add r1,r1,#2             @ increment index buffer (0D0A) 
    cmp r1,r6                @ end ?
    bge 4f
    add r2,r9,r1             @ new word begin
    mov r3,#0                @ init word length
    b 1b                     @ and loop   
4:
    mov r0,r5                @ return word counter 
    b 100f
96:                          @ display error messages
    ldr r0,iAdrszMessClose
    bl affichageMess     
    mov r0,#-1               @ error
    b 100f
97:
    ldr r0,iAdrszMessRead
    bl affichageMess 
    mov r0,#-1               @ error
    b 100f
99:
    ldr r0,iAdrszMessOpen
    bl  affichageMess    
    mov r0,#-1               @ error

 100:
    pop {r1-r9,pc}  
/***************************************************/
/*   word analyse                                  */
/***************************************************/
/* r0 contains a file buffer */
/* r1 contains array word address */
/* r2 contains array element */
traitWord:
    push {r1-r12,lr}        @ save registers
    mov r7,r0               @ save buffer address
    mov r8,r1               @ save array word address
    mov r9,r2               @ save size
    mov r10,#0              @ init index word array
    sub sp,sp,#80           @ reserve 80 byte on stack for work array
    mov fp,sp               @ work array address
1:
    mov r0,#st_word_end     @ structure size
    mla r0,r10,r0,r8        @ compute word item address 
    ldr r12,[r0,#st_word_adr]  @ load one word address
    ldr r5,[r0,#st_word_size]  @ load word size   
    mov r3,#0               @ index word
    mov r6,#0               @ size new word 
2:
    ldrb r4,[r12,r3]        @ load characters on odd index
    strb r4,[fp,r6]         @ store in wprk array on stack
    add r6,r6,#1            @ increment size new word
    add r3,r3,#2            @ increment index
    cmp r3,r5               @ end word ?
    ble 2b
    cmp r6,#WORDSIZE        @ length new word ok ?
    ble 10f
    mov r4,#0               @ store 0 final new word
    strb r4,[fp,r6]
                            @ search new word in word array by binary search
                            @ in french recherche dichotomique
    mov r3,#0               @ low index
    sub r4,r9,#1            @ high index = number of elements - 1
3:                          @ begin search loop
    cmp r3,r4               @ low > high
    bgt 10f                 @ not found
    add r7,r3,r4            @ compute (low + high) /2
    lsr r7,#1
    mov r1,#st_word_end     @ structure size
    mla r2,r7,r1,r8         @ compute word item address 
    ldr r0,[r2,#st_word_adr]  @ load word array address at new index r7                   
    mov r1,fp               @ search word address
    bl comparaison          @ alpha comparison
    cmp r0,#0
    beq 4f                  @ find  
    addlt r3,r7,#1          @ lower -> index low = index + 1
    subgt r4,r7,#1          @ bigger -> index high = index - 1
    b 3b                    @ and loop
    
4:                          @ ok -> display result
    mov r0,r12
    bl affichageMess
    ldr r0,iAdrszMessResult
    bl affichageMess
    mov r0,fp
    bl affichageMess
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    
10:    
    mov r6,#0                @ init new length new word
    add r10,r10,#1           @ increment index word array
    cmp r10,r9               @ end ?
    blt 1b                   @ no -> loop
    
100:
    add sp,sp,#80            @ stack alignement release work array  
    pop {r1-r12,pc}     

/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
/* for this file see task include a file in language ARM assembly*/
.include "../affichage.inc"
Output:
Program 32 bits start.
barbarian : brain
childbear : cider
corrigenda : cried
gargantuan : grata
headdress : hades
palladian : plain
propionate : point
salvation : slain
siltation : slain
slingshot : sight
statuette : saute
supersede : spree
supervene : spree
terminable : trial

Arturo

words: read.lines relative "unixdict.txt"

getOdd: function [w][
    odd: new ""
    loop.with:'i w 'ch [
        if even? i -> 'odd ++ ch
    ]
    odd
]

loop words 'word [
    ow: getOdd word
    if and? [4 < size ow][contains? words ow] ->
        print [word "=>" ow]
]
Output:
barbarian => brain 
childbear => cider 
corrigenda => cried 
gargantuan => grata 
headdress => hades 
palladian => plain 
propionate => point 
salvation => slain 
siltation => slain 
slingshot => sight 
statuette => saute 
supersede => spree 
supervene => spree 
terminable => trial

AWK

# syntax: GAWK -f ODD_WORDS.AWK unixdict.txt
#
# sorting:
#   PROCINFO["sorted_in"] is used by GAWK
#   SORTTYPE is used by Thompson Automation's TAWK
#
{ arr[$0]++ }
END {
    PROCINFO["sorted_in"] = "@ind_str_asc" ; SORTTYPE = 1
    main("13579","odd")
    main("02468","even")
    exit(0)
}
function main(pattern,text,  i,tmp,word) {
    pattern = sprintf("[%s]$",pattern)
    printf("\n%s:\n",text)
    for (word in arr) {
      tmp = ""
      for (i=1; i<=length(word); i++) {
        if (i ~ pattern) {
          tmp = tmp substr(word,i,1)
        }
      }
      if (length(tmp) > 4 && tmp in arr) {
        printf("%-11s %s\n",word,tmp)
      }
    }
}
Output:
odd:
barbarian   brain
childbear   cider
corrigenda  cried
gargantuan  grata
headdress   hades
palladian   plain
propionate  point
salvation   slain
siltation   slain
slingshot   sight
statuette   saute
supersede   spree
supervene   spree
terminable  trial

even:
cannonball  annal
importation motto
psychopomp  scoop
starvation  train
upholstery  posey

C++

#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <set>
#include <string>
#include <utility>
#include <vector>

using word_list = std::vector<std::pair<std::string, std::string>>;

void print_words(std::ostream& out, const word_list& words) {
    int n = 1;
    for (const auto& pair : words) {
        out << std::right << std::setw(2) << n++ << ": "
            << std::left << std::setw(14) << pair.first
            << pair.second << '\n';
    }
}

int main(int argc, char** argv) {
    const char* filename(argc < 2 ? "unixdict.txt" : argv[1]);
    std::ifstream in(filename);
    if (!in) {
        std::cerr << "Cannot open file '" << filename << "'.\n";
        return EXIT_FAILURE;
    }
    const int min_length = 5;
    std::string line;
    std::set<std::string> dictionary;
    while (getline(in, line)) {
        if (line.size() >= min_length)
            dictionary.insert(line);
    }

    word_list odd_words, even_words;

    for (const std::string& word : dictionary) {
        if (word.size() < min_length + 2*(min_length/2))
            continue;
        std::string odd_word, even_word;
        for (auto w = word.begin(); w != word.end(); ++w) {
            odd_word += *w;
            if (++w == word.end())
                break;
            even_word += *w;
        }

        if (dictionary.find(odd_word) != dictionary.end())
            odd_words.emplace_back(word, odd_word);

        if (dictionary.find(even_word) != dictionary.end())
            even_words.emplace_back(word, even_word);
    }

    std::cout << "Odd words:\n";
    print_words(std::cout, odd_words);

    std::cout << "\nEven words:\n";
    print_words(std::cout, even_words);

    return EXIT_SUCCESS;
}
Output:
Odd words:
 1: barbarian     brain
 2: childbear     cider
 3: corrigenda    cried
 4: gargantuan    grata
 5: headdress     hades
 6: palladian     plain
 7: propionate    point
 8: salvation     slain
 9: siltation     slain
10: slingshot     sight
11: statuette     saute
12: supersede     spree
13: supervene     spree
14: terminable    trial

Even words:
 1: cannonball    annal
 2: importation   motto
 3: psychopomp    scoop
 4: starvation    train
 5: upholstery    posey

Delphi

Works with: Delphi version 6.0


procedure ShowOddWords(Memo: TMemo);
var I,J: integer;
var W,S: string;
begin
{Iterate all entries in dictionary}
for I:=0 to UnixDict.Count-1 do
 if Length(UnixDict[I])>8 then	{Word must be >4, so every other is >8}
	begin
	W:=UnixDict[I];
	{Take every other letter}
	J:=1; S:='';
	while J<=Length(W) do
		begin
		S:=S+W[J];
		Inc(J,2);
		end;
	{Check if it is in Dictionary}
	if UnixDict.IndexOf(S)>0 then
		begin
		Memo.Lines.Add(W+' -> '+S);
		end;
	end;
end;
Output:
barbarian -> brain
childbear -> cider
corrigenda -> cried
gargantuan -> grata
headdress -> hades
palladian -> plain
propionate -> point
salvation -> slain
siltation -> slain
slingshot -> sight
statuette -> saute
supersede -> spree
supervene -> spree
terminable -> trial
Elapsed Time: 44.351 ms.


F#

// Odd words: Nigel Galloway. June 9th., 2021
let dict=seq{use n=System.IO.File.OpenText("unixdict.txt") in while not n.EndOfStream do yield n.ReadLine()}|>Seq.filter(fun n->n.Length>4)|>List.ofSeq
let fN g=let n=g|>String.mapi(fun n g->if n%2=0 then g else ' ')|>String.filter((<>)' ') in match List.contains n dict with true->Some(n,g) |_->None
dict|>Seq.filter(fun n->n.Length>6)|>Seq.choose fN|>Seq.iter(fun(n,g)->printfn "%s -> %s" g n)
Output:
barbarian -> brain
childbear -> cider
corrigenda -> cried
gargantuan -> grata
headdress -> hades
palladian -> plain
propionate -> point
salvation -> slain
siltation -> slain
slingshot -> sight
statuette -> saute
supersede -> spree
supervene -> spree
terminable -> trial

Factor

This is basically the same program as https://rosettacode.org/wiki/Alternade_words#Factor. <evens> is a virtual sequence representing the (zero-based) even indices of the input sequence, which this task calls the odd indices.

Works with: Factor version 0.99 2020-08-14
USING: formatting hash-sets io io.encodings.ascii io.files
kernel literals math sequences sequences.extras sets strings ;

<< CONSTANT: words $[ "unixdict.txt" ascii file-lines ] >>

CONSTANT: wordset $[ words >hash-set ]

: odd ( str -- newstr ) <evens> >string ;

"Odd words > 4:" print
words
[ length 8 > ] filter
[ odd wordset in? ] filter
[ dup odd "%-15s %s\n" printf ] each
Output:
Odd words > 4:
barbarian       brain
childbear       cider
corrigenda      cried
gargantuan      grata
headdress       hades
palladian       plain
propionate      point
salvation       slain
siltation       slain
slingshot       sight
statuette       saute
supersede       spree
supervene       spree
terminable      trial

FreeBASIC

#define NULL 0

type node
    word as string*32   'enough space to store any word in the dictionary
    nxt as node ptr
end type

function addword( tail as node ptr, word as string ) as node ptr
    'allocates memory for a new node, links the previous tail to it,
    'and returns the address of the new node
    dim as node ptr newnode = allocate(sizeof(node))
    tail->nxt = newnode
    newnode->nxt = NULL
    newnode->word = word
    return newnode
end function

function crunch( word as string ) as string
    dim as string ret = ""
    for i as uinteger = 1 to len(word) step 2
        ret += mid(word,i,1)
    next i
    return ret
end function

function length( word as string ) as uinteger
    'necessary replacement for the built-in len function, which in this
    'case would always return 32
    for i as uinteger = 1 to 32
        if asc(mid(word,i,1)) = 0 then return i-1
    next i
    return 999
end function

dim as string word
dim as node ptr tail = allocate( sizeof(node) )
dim as node ptr head = tail, curr = head, currj
tail->nxt = NULL
tail->word = "XXXXHEADER"

open "unixdict.txt" for input as #1
while true
    line input #1, word
    if word = "" then exit while
    tail = addword( tail, word )
wend
close #1

while curr->nxt <> NULL
    if length(curr->word) > 8 then word = crunch( curr->word ) else goto nextword
    currj = head
    while currj->nxt <> NULL
        if word = currj->word then print left(curr->word,length(curr->word));"   --->   ";word
        currj = currj->nxt
    wend
    nextword:
    curr = curr->nxt
wend
Output:
barbarian   --->   brain
childbear   --->   cider
corrigenda   --->   cried
gargantuan   --->   grata
headdress   --->   hades
palladian   --->   plain
propionate   --->   point
salvation   --->   slain
siltation   --->   slain
slingshot   --->   sight
statuette   --->   saute
supersede   --->   spree
supervene   --->   spree
terminable   --->   trial

And to discourage the creation of a whole new task for the even words, here they are. It requires only changing a 1 to a 2 in line 20, and an 8 to a 9 in line 50.

cannonball   --->   annal
importation   --->   motto
psychopomp   --->   scoop
starvation   --->   train
upholstery   --->   posey

FutureBasic

#plist NSAppTransportSecurity @{NSAllowsArbitraryLoads:YES}

include "NSLog.incl"

local fn WordsPassingTest( array as CFArrayRef, obj as CFTypeRef )
end fn = ( len(obj) > 4 )

local fn WordList as CFArrayRef
  CFURLRef url = fn URLWithString( @"http://wiki.puzzlers.org/pub/wordlists/unixdict.txt" )
  CFStringRef string = fn StringWithContentsOfURL( url, NSUTF8StringEncoding, NULL )
  CFArrayRef wordList = fn StringComponentsSeparatedByCharactersInSet( string, fn CharacterSetNewlineSet )
  IndexSetRef indexes = fn ArrayIndexesOfObjectsPassingTest( wordList, @fn WordsPassingTest, NULL )
  wordList = fn ArrayObjectsAtIndexes( wordList, indexes )
end fn = wordList

void local fn OddWords
  dispatchglobal
    CFArrayRef  wordList = fn WordList
    CFStringRef string
    long        i
    for string in wordList
      CFMutableStringRef wd = fn MutableStringWithCapacity(0)
      for i = 0 to len(string) step 2
        MutableStringAppendString( wd, mid(string,i,1) )
      next
      if ( len(wd) > 4 )
        if ( fn ArrayContainsObject( wordList, wd ) )
          NSLog(@"%@",wd)
        end if
      end if
    next
  dispatchend
end fn

fn OddWords

HandleEvents
Output:
brain
cider
cried
grata
hades
plain
point
slain
slain
sight
saute
spree
spree
trial

Go

package main

import (
    "bytes"
    "fmt"
    "io/ioutil"
    "log"
    "sort"
    "strings"
)

func main() {
    wordList := "unixdict.txt"
    b, err := ioutil.ReadFile(wordList)
    if err != nil {
        log.Fatal("Error reading file")
    }
    bwords := bytes.Fields(b)
    words := make([]string, len(bwords))
    for i, bword := range bwords {
        words[i] = string(bword)
    }
    count := 0
    fmt.Println("The odd words with length > 4 in", wordList, "are:")
    for _, word := range words {
        rword := []rune(word) // in case any non-ASCII
        if len(rword) > 8 {
            var sb strings.Builder
            for i := 0; i < len(rword); i += 2 {
                sb.WriteRune(rword[i])
            }
            s := sb.String()
            idx := sort.SearchStrings(words, s)      // binary search
            if idx < len(words) && words[idx] == s { // check not just an insertion point
                count = count + 1
                fmt.Printf("%2d: %-12s -> %s\n", count, word, s)
            }
        }
    }
}
Output:
The odd words with length > 4 in unixdict.txt are:
 1: barbarian    -> brain
 2: childbear    -> cider
 3: corrigenda   -> cried
 4: gargantuan   -> grata
 5: headdress    -> hades
 6: palladian    -> plain
 7: propionate   -> point
 8: salvation    -> slain
 9: siltation    -> slain
10: slingshot    -> sight
11: statuette    -> saute
12: supersede    -> spree
13: supervene    -> spree
14: terminable   -> trial

J

In J, the index of the first character is 0, and the index of the second character is 1, thus:

   >(([-.-.) (#~ $&0 1@#)&.>) (#~ 4<#@>)cutLF fread'unixdict.txt'
annal
motto
posey
scoop
train

However, some languages have 1 for the index of the first character, which would have given us:

   >(([-.-.) (#~ $&1 0@#)&.>) (#~ 4<#@>)cutLF fread'unixdict.txt'
brain
cider
cried
grata
hades
plain
point
saute
sight
slain
spree
trial

Java

import java.io.*;
import java.util.*;

public class OddWords {
    public static void main(String[] args) {
        try {
            Set<String> dictionary = new TreeSet<>();
            final int minLength = 5;
            String fileName = "unixdict.txt";
            if (args.length != 0)
                fileName = args[0];
            try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.length() >= minLength)
                        dictionary.add(line);
                }
            }
            StringBuilder word1 = new StringBuilder();
            StringBuilder word2 = new StringBuilder();
            List<StringPair> evenWords = new ArrayList<>();
            List<StringPair> oddWords = new ArrayList<>();
            for (String word : dictionary) {
                int length = word.length();
                if (length < minLength + 2 * (minLength/2))
                    continue;
                word1.setLength(0);
                word2.setLength(0);
                for (int i = 0; i < length; ++i) {
                    if ((i & 1) == 0)
                        word1.append(word.charAt(i));
                    else
                        word2.append(word.charAt(i));
                }
                String oddWord = word1.toString();
                String evenWord = word2.toString();
                if (dictionary.contains(oddWord))
                    oddWords.add(new StringPair(word, oddWord));
                if (dictionary.contains(evenWord))
                    evenWords.add(new StringPair(word, evenWord));
            }
            System.out.println("Odd words:");
            printWords(oddWords);
            System.out.println("\nEven words:");
            printWords(evenWords);
        } catch (Exception e)  {
            e.printStackTrace();
        }
    }

    private static void printWords(List<StringPair> strings) {
        int n = 1;
        for (StringPair pair : strings) {
            System.out.printf("%2d: %-14s%s\n", n++,
                                    pair.string1, pair.string2);
        }
    }

    private static class StringPair {
        private String string1;
        private String string2;
        private StringPair(String s1, String s2) {
            string1 = s1;
            string2 = s2;
        }
    }
}
Output:
Odd words:
 1: barbarian     brain
 2: childbear     cider
 3: corrigenda    cried
 4: gargantuan    grata
 5: headdress     hades
 6: palladian     plain
 7: propionate    point
 8: salvation     slain
 9: siltation     slain
10: slingshot     sight
11: statuette     saute
12: supersede     spree
13: supervene     spree
14: terminable    trial

Even words:
 1: cannonball    annal
 2: importation   motto
 3: psychopomp    scoop
 4: starvation    train
 5: upholstery    posey

jq

Works with: jq

Works with gojq, the Go implementation of jq if `keys_unsorted` is replaced by `keys`

Counting the letters from 1...

  def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;

  INDEX(inputs | select(length>4); .)
  | .  as $dict
  | keys_unsorted[]
  | select(length > 8)
  | (explode | [.[range(0;length;2)]] | implode) as $odd
  | select( ($odd|length > 4) and $dict[$odd])
  | "\(lpad(10)) : \($odd)"
Output:

Illustrative invocation: jq -nrR -f program.jq unixdict.txt

 barbarian : brain
 childbear : cider
corrigenda : cried
gargantuan : grata
 headdress : hades
 palladian : plain
propionate : point
 salvation : slain
 siltation : slain
 slingshot : sight
 statuette : saute
 supersede : spree
 supervene : spree
terminable : trial


Julia

See Alternade_words#Julia for the foreachword function.

isoddword(w, d) = (o = mapreduce(i -> w[i], *, 1:2:length(w)); haskey(d, o) ? rpad(w, 16) * ":  " * o : "")
foreachword("unixdict.txt", isoddword, minlen=9, numcols=1)
Output:
Word source: unixdict.txt

barbarian       :  brain
childbear       :  cider
corrigenda      :  cried
gargantuan      :  grata
headdress       :  hades
palladian       :  plain
propionate      :  point
salvation       :  slain
siltation       :  slain
slingshot       :  sight
statuette       :  saute
supersede       :  spree
supervene       :  spree
terminable      :  trial

Lua

minOddWordLength = 5
minWordLength    = minOddWordLength*2-1

dict = {}
for word in io.lines('unixdict.txt') do
  local n = #word
  if n >= minOddWordLength then -- skip words that are too short
    dict[word] = n
  end
end

for word, len in pairs(dict) do
  if len >= minWordLength then
    local odd  = ""
    for o, _ in word:gmatch("(.)(.?)") do
      odd = odd .. o
    end
    if dict[odd] then
      print(string.format("%10s → %s", word, odd))
    end
  end
end
Output:

Note: Output will not be alphabetical.

 barbarian → brain
 childbear → cider
corrigenda → cried
 supervene → spree
 siltation → slain
terminable → trial
 supersede → spree
 slingshot → sight
propionate → point
 salvation → slain
 palladian → plain
gargantuan → grata
 headdress → hades
 statuette → saute

Mathematica/Wolfram Language

dict = Import["https://web.archive.org/web/20180611003215/http://www.puzzlers.org/pub/wordlists/unixdict.txt"];
dict //= StringSplit[#, "\n"] &;
ClearAll[OddLetters, OddWordQ]
OddLetters[s_String] := StringTake[s, {1, -1, 2}]
OddWordQ[s_String] := Module[{},
  If[StringLength[s] >= 9,
   MemberQ[dict, OddLetters[s]]
   ,
   False
   ]
  ]
{#, OddLetters[#]} & /@ Select[dict, OddWordQ] // Grid
Output:
barbarian	brain
childbear	cider
corrigenda	cried
gargantuan	grata
headdress	hades
palladian	plain
propionate	point
salvation	slain
siltation	slain
slingshot	sight
statuette	saute
supersede	spree
supervene	spree
terminable	trial

Nim

import sets, strformat, sugar

const DictFile = "unixdict.txt"

let words = collect(initHashSet, for word in DictFile.lines: {word})

var count = 0
for word in DictFile.lines:
  var oddWord: string
  for i in countup(0, word.high, 2): oddWord.add word[i]  # First odd char is at index 0.
  if oddWord.len > 4 and oddWord in words:
    inc count
    echo &"{count:2}: {word:12} →  {oddWord}"
Output:
 1: barbarian    →  brain
 2: childbear    →  cider
 3: corrigenda   →  cried
 4: gargantuan   →  grata
 5: headdress    →  hades
 6: palladian    →  plain
 7: propionate   →  point
 8: salvation    →  slain
 9: siltation    →  slain
10: slingshot    →  sight
11: statuette    →  saute
12: supersede    →  spree
13: supervene    →  spree
14: terminable   →  trial

Perl

#!/usr/bin/perl

@ARGV = 'unixdict.txt';
chomp( my @words = <> );
my %dict;
@dict{ grep length > 4, @words} = ();
for ( @words )
  {
  my $oddword = s/(.).?/$1/gr;
  exists $dict{$oddword} and print " $_ $oddword\n";
  }
Output:
 barbarian brain
 childbear cider
 corrigenda cried
 gargantuan grata
 headdress hades
 palladian plain
 propionate point
 salvation slain
 siltation slain
 slingshot sight
 statuette saute
 supersede spree
 supervene spree
 terminable trial

Phix

with javascript_semantics
sequence words = unix_dict()
function oddc(integer /*ch*/, idx) return remainder(idx,2)=1 end function
function oddch(string word) return filter(word,oddc) end function
function over4(string word) return length(word)>4 end function
words = filter(filter(apply(words,oddch),over4),"in",words)
printf(1,"%d odd words found: %s\n",{length(words),join(shorten(words,"",3),", ")})
Output:
14 odd words found: brain, cider, cried, ..., spree, spree, trial

Alternative

Slightly more traditional, same output.

with javascript_semantics
sequence words = unix_dict(),
         res = {}
for i=1 to length(words) do
    string word = words[i], wodd = ""
    for oddchar=1 to length(word) by 2 do
        wodd &= word[oddchar]
    end for
    if length(wodd)>4 
    and find(wodd,words) then
        res = append(res,wodd)
    end if
end for
printf(1,"%d odd words found: %s\n",{length(res),join(shorten(res,"",3),", ")})

Python

Procedural

This implementation prints only the unique odd words which appear in unixdict.txt unlike other implementations on this page which print some words twice. The minimum base word length has to be 9 since the problem statement says that odd word lengths must be greater than 4.

Tested on Python 3+, the file download will work only if the link is still active. It is possible that you may be able to fetch the file in your browser but download via code may still fail. Check whether you are connected to a VPN, it works on open networks.

#Aamrun, 4th October 2021

import urllib.request
urllib.request.urlretrieve("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt", "unixdict.txt")

dictionary = open("unixdict.txt","r")

wordList = dictionary.read().split('\n')

dictionary.close()

oddWordSet = set({})

for word in wordList:
    if len(word)>=9 and word[::2] in wordList:
        oddWordSet.add(word[::2])

[print(i) for i in sorted(oddWordSet)]
Output:
brain
cider
cried
grata
hades
plain
point
saute
sight
slain
spree
trial

Functional

Defining a dictionary of oddWords, keyed by their sources:

'''Odd words'''

from os.path import expanduser
from json import dumps


# oddPairs :: Int -> [String] -> Dict
def oddPairs(minLength):
    '''A dictionary of (word::oddWord) pairs
       in which the words are drawn from a given wordList,
       and the oddWords have at least a minimum length.
    '''
    def go(wordList):
        lexicon = set(wordList)
        return {
            k: v for k, v in ((w, w[::2]) for w in wordList)
            if minLength <= len(v) and v in lexicon
        }
    return go


# ------------------------- TEST -------------------------
# main :: IO ()
def main():
    '''Odd words of 5 or more characters, paired with their
       sources, which are drawn from a local unixdict.txt
    '''
    print(dumps(
        oddPairs(5)(
            readFile('~/unixdict.txt').split('\n')
        ),
        indent=4
    ))


# ----------------------- GENERIC ------------------------

# readFile :: FilePath -> IO String
def readFile(fp):
    '''The contents of any file at the path
       derived by expanding any ~ in fp.
    '''
    with open(expanduser(fp), 'r', encoding='utf-8') as f:
        return f.read()


# MAIN ---
if __name__ == '__main__':
    main()
Output:
{
    "barbarian": "brain",
    "childbear": "cider",
    "corrigenda": "cried",
    "gargantuan": "grata",
    "headdress": "hades",
    "palladian": "plain",
    "propionate": "point",
    "salvation": "slain",
    "siltation": "slain",
    "slingshot": "sight",
    "statuette": "saute",
    "supersede": "spree",
    "supervene": "spree",
    "terminable": "trial"
}

Quackery

  [ stack ]                      is sift.test  (     --> s   )
  protect sift.test

  [ ]'[ sift.test put
    [] [] rot 
    witheach
      [ sift.test share do iff
          [ nested join ]
        else 
          [ swap dip 
            [ nested join ] ] ]
     sift.test release ]         is siftwith   (   [ --> [ [ )

  [ 1 & ]                        is odd        (   n --> b   )

  [ stack ]                      is dict       (     --> s   )

  [ dict share
   dup dip find found ]          is indict     (   $ --> b   )

  $ "unixdict.txt" sharefile drop
  nest$ siftwith [ dup size 4 > ]
  nip dict put
 
  dict share 
  siftwith [ dup size 8 > ]
  nip

  witheach
  [ siftwith [ i^ odd ]
    drop
    dup indict iff
      [ echo$ cr ]
    else drop ]

  dict release
Output:
brain
cider
cried
grata
hades
plain
point
slain
slain
sight
saute
spree
spree
trial

Raku

my %words = 'unixdict.txt'.IO.slurp.words.map: * => 1;

my (@odds, @evens);

for %words {
    next if .key.chars < 9;
    my $odd  = .key.comb[0,2 … *].join;
    @odds.push(.key => $odd) if %words{$odd} and $odd.chars > 4;
    my $even = .key.comb[1,3 … *].join;
    @evens.push(.key => $even) if %words{$even} and $even.chars > 4;
}

.put for flat 'Odd words > 4:', @odds.sort;

.put for flat "\nEven words > 4:", @evens.sort;
Output:
Odd words > 4:
barbarian	brain
childbear	cider
corrigenda	cried
gargantuan	grata
headdress	hades
palladian	plain
propionate	point
salvation	slain
siltation	slain
slingshot	sight
statuette	saute
supersede	spree
supervene	spree
terminable	trial

Even words > 4:
cannonball	annal
importation	motto
psychopomp	scoop
starvation	train
upholstery	posey

REXX

Any words longer than ten characters are truncated in the output.

version 1

/* REXX */
fid='d:\unix.txt'
ww.=0   /* ww.*  the words to be analyzed     */
w.=0    /* w.word = 1 if word is in unix.txt  */
Do While lines(fid)>0
  l=linein(fid)     /* a word                 */
  ll=length(l)
  w.l=1             /*  word is in unix.txt   */
  If ll>=9 Then Do  /* worth to be analyzed   */
    z=ww.0+1        /* add it to the list     */
    ww.z=l
    ww.0=z
    End
  End
n=0
Do i=1 To ww.0
  wodd=wodd(ww.i)
  If w.wodd Then Do
    n=n+1
    Say format(n,3) left(ww.i,10) wodd
    End
  End
Exit
wodd: Procedure
/* use odd indexed letters */
  Parse Arg w
  wo=''
  Do i=1 To length(w)
    If i//2=1 Then
      wo=wo||substr(w,i,1)
    End
  Return wo
Output:
  1 barbarian  brain
  2 childbear  cider
  3 corrigenda cried
  4 gargantuan grata
  5 headdress  hades
  6 palladian  plain
  7 propionate point
  8 salvation  slain
  9 siltation  slain
 10 slingshot  sight
 11 statuette  saute
 12 supersede  spree
 13 supervene  spree
 14 terminable trial

version 2, caseless

This REXX version doesn't care what order the words in the dictionary are in,   nor does it care what
case  (lower/upper/mixed)  the words are in,   the search for alternates is   caseless.

It also allows the minimum length to be specified on the command line (CL) as well as the dictionary file identifier.

/*REXX program finds all the  caseless  "odd words"  (within an identified dictionary). */
parse arg minL iFID .                            /*obtain optional arguments from the CL*/
if minL=='' | minL=="," then minL= 5             /*Not specified?  Then use the default.*/
if iFID=='' | iFID=="," then iFID='unixdict.txt' /* "      "         "   "   "     "    */
@.=                                              /*default value of any dictionary word.*/
           do #=1  while lines(iFID)\==0         /*read each word in the file  (word=X).*/
           x= strip( linein( iFID) )             /*pick off a word from the input line. */
           $.#= x;       upper x;       @.x= .   /*save: original case and the semaphore*/
           end   /*#*/                           /* [↑]   semaphore name is uppercased. */
#= # - 1                                         /*adjust word count because of DO loop.*/
minW= minL * 2 - 1                               /*minimum width of a word to be usable.*/
say copies('─', 30)     #     "words in the dictionary file: "       iFID
say
finds= 0                                         /*count of the  "odd words"  found.    */
        do j=1  for #;         L= length($.j)    /*process all the words that were found*/
        if L<minW  then iterate                  /*Is word too short?   Then ignore it. */
        ow=                                      /*initialize the  "odd word".          */
                   do k=1  by 2  to  L           /*only use odd indexed letters in word.*/
                   ow= ow  ||  substr($.j, k, 1) /*construct the  "odd word".           */
                   end   /*k*/
        owU= ow;               upper owU         /*uppercase the odd word to be caseless*/
        if @.owU==''  then iterate               /*if not extant,  then skip this word. */
        finds= finds + 1                         /*bump the count of "odd words" found. */
        say right(left($.j, 20), 24) left(ow, 9) /*indent original word for readability.*/
        end        /*j*/
                                                 /*stick a fork in it,  we're all done. */
say copies('─', 30)      finds     ' "odd words" found with a minimum length of '    minL
output   when using the default input:
────────────────────────────── 25104 words in the dictionary file:  unixdict.txt
    barbarian            brain
    childbear            cider
    corrigenda           cried
    gargantuan           grata
    headdress            hades
    palladian            plain
    propionate           point
    salvation            slain
    siltation            slain
    slingshot            sight
    statuette            saute
    supersede            spree
    supervene            spree
    terminable           trial
────────────────────────────── 14  "odd words" found with a minimum length of  5

Ring

cStr = read("unixdict.txt")
wordList = str2list(cStr)
num = 0

see "Odd words are:" + nl

for n = 1 to len(wordList)
    strWord = ""
    len = len(wordList[n])
    for m = 1 to len step 2
        strWord = strWord + wordList[n][m]
    next
    ind = find(wordList,strWord) 
    if ind > 0  and len(strWord) > 4
       num = num + 1
       see "" + num + ". " + wordList[n] + " >> " + strWord + nl
    ok
next

Output:

Odd words are:
1. barbarian >> brain
2. childbear >> cider
3. corrigenda >> cried
4. gargantuan >> grata
5. headdress >> hades
6. palladian >> plain
7. propionate >> point
8. salvation >> slain
9. siltation >> slain
10. slingshot >> sight
11. statuette >> saute
12. supersede >> spree
13. supervene >> spree
14. terminable >> trial

RPL

Works with: Halcyon Calc version 4.2.7
≪ { }
   1 UnixDict SIZE FOR w
     ‘UnixDict’ w GET      
     IF DUP SIZE 9 ≥ THEN 
        ""
        1 OVER SIZE FOR k
           OVER k DUP SUB +
        2 STEP
        SWAP DROP
        IF UnixDict OVER POS THEN 
           IF DUP2 POS NOT THEN + ELSE DROP END 
        ELSE DROP END
     ELSE DROP END 
   NEXT
≫ ‘ODDW’ STO
Output:
1: { "brain" "cider" "cried" "grata" "hades" "plain" "point" "slain" "slain" "sight" "saute" "spree" "trial" }

Ruby

Binary search (bsearch) speeds things up.

dict = File.readlines("unixdict.txt", chomp: true).reject{|w| w.size < 5}
dict.each do |w|
  next if w.size < 9
  odd = w.chars.each_slice(2).map(&:first).join
  puts w.ljust(14) + odd if dict.bsearch{|w| odd <=> w} 
end
Output:
barbarian      brain
childbear      cider
corrigenda     cried
gargantuan     grata
headdress      hades
palladian      plain
propionate     point
salvation      slain
siltation      slain
slingshot      sight
statuette      saute
supersede      spree
supervene      spree
terminable     trial

Rust

use std::collections::BTreeSet;
use std::fs::File;
use std::io::{self, BufRead};

fn load_dictionary(filename: &str, min_length: usize) -> std::io::Result<BTreeSet<String>> {
    let file = File::open(filename)?;
    let mut dict = BTreeSet::new();
    for line in io::BufReader::new(file).lines() {
        let word = line?;
        if word.len() >= min_length {
            dict.insert(word);
        }
    }
    Ok(dict)
}

fn print_words(words: &[(&String, String)]) {
    for (i, (a, b)) in words.iter().enumerate() {
        println!("{:2}: {:<14}{}", i + 1, a, b);
    }
}

fn main() {
    let min_length = 5;
    match load_dictionary("unixdict.txt", min_length) {
        Ok(dictionary) => {
            let mut odd_words = Vec::new();
            let mut even_words = Vec::new();
            for word in &dictionary {
                if word.len() < min_length + 2 * (min_length / 2) {
                    continue;
                }
                let mut odd_word = String::new();
                let mut even_word = String::new();
                for (i, c) in word.chars().enumerate() {
                    if (i & 1) == 0 {
                        odd_word.push(c);
                    } else {
                        even_word.push(c);
                    }
                }
                if dictionary.contains(&odd_word) {
                    odd_words.push((word, odd_word));
                }
                if dictionary.contains(&even_word) {
                    even_words.push((word, even_word));
                }
            }
            println!("Odd words:");
            print_words(&odd_words);
            println!("\nEven words:");
            print_words(&even_words);
        }
        Err(error) => eprintln!("{}", error),
    }
}
Output:
Odd words:
 1: barbarian     brain
 2: childbear     cider
 3: corrigenda    cried
 4: gargantuan    grata
 5: headdress     hades
 6: palladian     plain
 7: propionate    point
 8: salvation     slain
 9: siltation     slain
10: slingshot     sight
11: statuette     saute
12: supersede     spree
13: supervene     spree
14: terminable    trial

Even words:
 1: cannonball    annal
 2: importation   motto
 3: psychopomp    scoop
 4: starvation    train
 5: upholstery    posey

Swift

import Foundation

let minLength = 5

func loadDictionary(_ path: String) throws -> Set<String> {
    let contents = try String(contentsOfFile: path, encoding: String.Encoding.ascii)
    return Set<String>(contents.components(separatedBy: "\n").filter{$0.count >= minLength})
}

func pad(string: String, width: Int) -> String {
    return string.count >= width ? string
        : string + String(repeating: " ", count: width - string.count)
}

func printWords(words: [(String,String)]) {
    for (n, (word1, word2)) in words.enumerated() {
        print("\(String(format: "%2d", n + 1)): \(pad(string: word1, width: 14))\(word2)")
    }
}

do {
    let dictionary = try loadDictionary("unixdict.txt")
    var oddWords: [(String, String)] = []
    var evenWords: [(String, String)] = []
    for word in dictionary {
        if word.count < minLength + 2*(minLength/2) {
            continue
        }
        var oddWord = ""
        var evenWord = ""
        for (i, c) in word.enumerated() {
            if (i & 1) == 0 {
                oddWord.append(c)
            } else {
                evenWord.append(c)
            }
        }
        if dictionary.contains(oddWord) {
            oddWords.append((word, oddWord))
        }
        if dictionary.contains(evenWord) {
            evenWords.append((word, evenWord))
        }
    }
    oddWords.sort(by: {$0.0 < $1.0})
    evenWords.sort(by: {$0.0 < $1.0})
    print("Odd words:")
    printWords(words: oddWords)
    print("\nEven words:")
    printWords(words: evenWords)
} catch {
    print(error.localizedDescription)
}
Output:
Odd words:
 1: barbarian     brain
 2: childbear     cider
 3: corrigenda    cried
 4: gargantuan    grata
 5: headdress     hades
 6: palladian     plain
 7: propionate    point
 8: salvation     slain
 9: siltation     slain
10: slingshot     sight
11: statuette     saute
12: supersede     spree
13: supervene     spree
14: terminable    trial

Even words:
 1: cannonball    annal
 2: importation   motto
 3: psychopomp    scoop
 4: starvation    train
 5: upholstery    posey

V (Vlang)

import os

fn main() {
	mut num := 0
	mut word_arr := []u8{}
	mut odd_list :=""
    word_list := os.read_file("./unixdict.txt") or {println(err) exit(-1)}.split_into_lines()
	for word in word_list {
		if word.len > 8 {
			for idx, chars in word {if idx % 2 == 0 {word_arr << chars}}
			if word_list.contains(word_arr.bytestr()) && !odd_list.contains(word) && word_arr.len > 4 {
				num++
				odd_list += "${num}. ${word} >> ${word_arr.bytestr()} \n"
			}
		}
		word_arr.clear()
	}
	println(odd_list)
}
Output:
1. barbarian >> brain 
2. childbear >> cider 
3. corrigenda >> cried 
4. gargantuan >> grata 
5. headdress >> hades 
6. palladian >> plain 
7. propionate >> point 
8. salvation >> slain 
9. siltation >> slain 
10. slingshot >> sight 
11. statuette >> saute 
12. supersede >> spree 
13. supervene >> spree 
14. terminable >> trial

Wren

Library: Wren-fmt
Library: Wren-sort
Library: Wren-iterate
import "io" for File
import "./fmt" for Fmt
import "./sort" for Find
import "./iterate" for Stepped

var wordList = "unixdict.txt" // local copy
var words = File.read(wordList).trimEnd().split("\n")
var count = 0
System.print("The odd words with length > 4 in %(wordList) are:")
for (word in words) {
    if (word.count > 8) {
        var s = ""
        var chars = word.toList // in case any non-ASCII
        for (i in Stepped.new(0...chars.count, 2)) s = s + chars[i]
        if (Find.first(words, s) >= 0) { // binary search
            count = count + 1
            Fmt.print("$2d: $-12s -> $s", count, word, s)
        }
    }
}
Output:
The odd words with length > 4 in unixdict.txt are:
 1: barbarian    -> brain
 2: childbear    -> cider
 3: corrigenda   -> cried
 4: gargantuan   -> grata
 5: headdress    -> hades
 6: palladian    -> plain
 7: propionate   -> point
 8: salvation    -> slain
 9: siltation    -> slain
10: slingshot    -> sight
11: statuette    -> saute
12: supersede    -> spree
13: supervene    -> spree
14: terminable   -> trial

XPL0

string  0;              \use zero-terminated strings
int     Dict(26000);    \pointers to words (enough for unixdict.txt)
int     DictSize;       \actual number of pointers in Dict

func    StrCmp(A, B);   \Compare string A to B
char    A, B;           \Returns: >0 if A>B, =0 if A=B, and <0 if A<B
int     I;
[for I:= 0 to -1>>1 do
        [if A(I) # B(I) then return A(I) - B(I);
         if A(I) = 0 then return 0;
        ];
];      \StrCmp

func    LookUp(Word);   \Return 'true' if Word is in Dict
char    Word;
int     Lo, Hi, I, Cmp;
[Lo:= 0;  Hi:= DictSize-1;
loop    [I:= (Lo+Hi) / 2; \binary search
        Cmp:= StrCmp(Word, Dict(I));
        if Cmp < 0 then Hi:= I-1 else Lo:= I+1;
        if Cmp = 0 then return true;
        if Lo > Hi then return false;
        ];
];      \LookUp

int     I, I0, DI, Ch, Count;
char    Word, Alt0(25);
def     Tab=$09, LF=$0A, CR=$0D, EOF=$1A;

[FSet(FOpen("unixdict.txt", 0), ^I); \load dictionary
OpenI(3);                        \assume alphabetical order and all lowercase
DI:= 0;                          \ignore non-alpha characters: 0..9, ' and &
repeat  Dict(DI):= Reserve(0);   \get pointer to memory used to store Word
        Word:= Dict(DI);
        I:= 0;
        loop    [repeat Ch:= ChIn(3) until Ch # CR;     \remove possible CR
                if Ch=LF or Ch=EOF then quit;
                Word(I):= Ch;
                I:= I+1;
                ];
        Word(I):= 0;            \terminate Word string
        I:= Reserve(I+1);       \reserve memory used for Word
        DI:= DI+1;              \next dictionary entry
until   Ch = EOF;
DictSize:= DI;

DI:= 0;  Count:= 0;
repeat  Word:= Dict(DI);        \print out all odd words
        I:= 0;  I0:= 0;
        loop    [Ch:= Word(I);
                if Ch = 0 then quit;
                if (I&1) = 0 then [Alt0(I0):= Ch;  I0:= I0+1];
                I:= I+1;
                ];
        if I >= 9 then          \Word must have at least 9 chars
                [Alt0(I0):= 0;
                if LookUp(Alt0) then
                        [Count:= Count+1;
                        IntOut(0, Count);  ChOut(0, Tab);
                        Text(0, Word);  ChOut(0, Tab);
                        Text(0, Alt0);  ChOut(0, Tab);
                        CrLf(0);
                        ];
                ];
        DI:= DI+1;
until   DI >= DictSize;
]
Output:
1       barbarian       brain   
2       childbear       cider   
3       corrigenda      cried   
4       gargantuan      grata   
5       headdress       hades   
6       palladian       plain   
7       propionate      point   
8       salvation       slain   
9       siltation       slain   
10      slingshot       sight   
11      statuette       saute   
12      supersede       spree   
13      supervene       spree   
14      terminable      trial