Words from neighbour ones

From Rosetta Code
Revision as of 09:47, 5 May 2022 by Drkameleon (talk | contribs) (Added Arturo implementation)
Words from neighbour ones 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.
Task

Use the dictionary   unixdict.txt

Ignore any word in the dictionary whose length is less than 9.


Let's take the words from next characters:
1 <= n < (dictionary length) - 9.
char1 = 1st character of         nth   word.
char2 = 2nd character of  (n+1)th  word.
char3 = 3rd character of  (n+2)th  word.
   
char9 = 9th character of  (n+8)th  word.


Concatenate (append) the nine characters by:

      newword = char1 + char2 + char3 + ... + char9 


If   newword   is in the dictionary, then show on this page.

Length of  newword = 9


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

<lang 11l>V wordList = File(‘unixdict.txt’).read().split("\n")

V filteredWords = wordList.filter(chosenWord -> chosenWord.len >= 9)

L(word) filteredWords[0 .< (len)-9]

  V position = filteredWords.index(word)
  V newWord = (0..8).map(i -> :filteredWords[@position + i][i]).join(‘’)
  I newWord C filteredWords
     print(newWord)</lang>
Output:
applicate
architect
astronomy
christine
christoph
committee
committee
committee
committee
committee
composite
constrict
constrict
construct
different
extensive
greenwood
implement
improvise
intercept
interpret
interrupt
interrupt
philosoph
prescript
receptive
telephone
transcend
transcend
transport
transpose

AppleScript

Core language

<lang applescript>on task()

   -- Since the task specifically involves unixdict.txt, this code's written in
   -- the knowlege that the words are on individual lines and in dictionary order.
   set dictPath to (path to desktop as text) & "unixdict.txt"
   script o
       property wordList : paragraphs of (read file dictPath as «class utf8»)
       property matches : {}
   end script
   -- Zap words with fewer than 9 characters and work with what's left.
   repeat with i from 1 to (count o's wordList)
       if ((count item i of o's wordList) < 9) then set item i of o's wordList to missing value
   end repeat
   set o's wordList to o's wordList's every text
   set wordListCount to (count o's wordList)
   set previousNewWord to missing value
   repeat with i from 1 to (wordListCount - 8)
       set newWord to character 1 of item i of o's wordList
       set j to (i - 1)
       repeat with k from 2 to 9
           set newWord to newWord & character k of item (j + k) of o's wordList
       end repeat
       -- Since wordList's known to be in dictionary order, a lot of time can be saved
       -- by only checking the necessary few words ahead for a match instead of
       -- using AppleScript's 'is in' or 'contains' commands, which check the entire list.
       if (newWord is not previousNewWord) then
           repeat with j from i to wordListCount
               set thisWord to item j of o's wordList
               if (newWord comes after thisWord) then
               else
                   if (newWord is thisWord) then set end of o's matches to newWord
                   exit repeat
               end if
           end repeat
           set previousNewWord to newWord
       end if
   end repeat
   
   return o's matches

end task

task()</lang>

Output:

<lang applescript>{"applicate", "architect", "astronomy", "christine", "christoph", "committee", "composite", "constrict", "construct", "different", "extensive", "greenwood", "implement", "improvise", "intercept", "interpret", "interrupt", "philosoph", "prescript", "receptive", "telephone", "transcend", "transport", "transpose"}</lang>

AppleScriptObjC

Same output as above. <lang applescript>use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later use framework "Foundation" use scripting additions

on task()

   set |⌘| to current application
   set dictPath to (POSIX path of (path to desktop)) & "unixdict.txt"
   set dictText to |⌘|'s class "NSString"'s stringWithContentsOfFile:(dictPath) ¬
       usedEncoding:(missing value) |error|:(missing value)
   set newlineSet to |⌘|'s class "NSCharacterSet"'s newlineCharacterSet()
   set wordArray to dictText's componentsSeparatedByCharactersInSet:(newlineSet)
   -- Lose words with fewer than 9 characters.
   set filter to |⌘|'s class "NSPredicate"'s predicateWithFormat:("self MATCHES '.{9,}+'")
   set relevantWords to wordArray's filteredArrayUsingPredicate:(filter)
   
   -- Creating the new words is most easily and efficiently done with core AppleScript.
   script o
       property wordList : relevantWords as list
       property newWords : {}
   end script
   repeat with i from 1 to ((count o's wordList) - 8)
       set newWord to character 1 of item i of o's wordList
       set j to (i - 1)
       repeat with k from 2 to 9
           set newWord to newWord & character k of item (j + k) of o's wordList
       end repeat
       set end of o's newWords to newWord
   end repeat
   
   -- But Foundation sets are good for filtering the results.
   set matches to |⌘|'s class "NSMutableOrderedSet"'s orderedSetWithArray:(o's newWords)
   tell matches to intersectSet:(|⌘|'s class "NSSet"'s setWithArray:(relevantWords))
   
   return (matches's array()) as list

end task

task()</lang>

Arturo

Translation of: Nim

<lang rebol>wordset: map read.lines relative "unixdict.txt" => strip wordset: select wordset 'word -> 9 =< size word

lastWord: "" newWord: " " count: 0

loop 0..(size wordset)-9 'i [

   loop 0..8 'j -> newWord\[j]: wordset\[i+j]\[j]
   if and? [in? newWord wordset][lastWord <> newWord][
       count: count + 1
       print [(pad to :string count 3)++":" newWord]
       lastWord: new newWord
   ]

]</lang>

Output:
  1: applicate 
  2: architect 
  3: astronomy 
  4: christine 
  5: christoph 
  6: committee 
  7: composite 
  8: constrict 
  9: construct 
 10: different 
 11: extensive 
 12: greenwood 
 13: implement 
 14: improvise 
 15: intercept 
 16: interpret 
 17: interrupt 
 18: philosoph 
 19: prescript 
 20: receptive 
 21: telephone 
 22: transcend 
 23: transport 
 24: transpose

AutoHotkey

<lang AutoHotkey>FileRead, wList, % A_Desktop "\unixdict.txt" for word in neighbour(wList)

   result .= word (Mod(A_Index, 6) ? "`t" : "`n")

MsgBox, 262144, , % result return

neighbour(wList){

   words := [], wordExist := [], oRes := []
   for i, w in StrSplit(wList, "`n", "`r")
   {
       if (StrLen(w) < 9)
           continue
       words.Push(w)
       wordExist[w] := true
   }
   loop % words.Count()-9
   {
       n := A_Index
       newword := ""
       loop 9
           newword .= SubStr(words[n+A_Index-1], A_Index, 1)
       if wordExist[newword]
           oRes[newword] := true
   }
   return oRes

}</lang>

Output:
applicate	architect	astronomy	christine	christoph	committee
composite	constrict	construct	different	extensive	greenwood
implement	improvise	intercept	interpret	interrupt	philosoph
prescript	receptive	telephone	transcend	transport	transpose

AWK

<lang AWK>

  1. syntax: GAWK -f WORDS_FROM_NEIGHBOUR_ONES.AWK unixdict.txt

{ if (length($0) < 9) { next }

   arr1[++n] = $0
   arr2[$0] = ""

} END {

   for (i=1; i<=n; i++) {
     word = substr(arr1[i],1,1)
     for (j=2; j<=9; j++) {
       if (!((i+j) in arr1)) { continue }
       word = word substr(arr1[i+j],j,1)
     }
     if (word in arr2) {
       printf("%s\n",word)
       delete arr2[word] # eliminate duplicates
     }
   }
   exit(0)

} </lang>

Output:
applicate
architect
astronomy
christine
christoph
committee
composite
constrict
construct
different
extensive
greenwood
implement
improvise
intercept
interpret
interrupt
philosoph
prescript
receptive
telephone
transcend
transport
transpose

C

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <string.h>
  1. define MAX_WORD_SIZE 80
  2. define MIN_LENGTH 9
  3. define WORD_SIZE (MIN_LENGTH + 1)

void fatal(const char* message) {

   fprintf(stderr, "%s\n", message);
   exit(1);

}

void* xmalloc(size_t n) {

   void* ptr = malloc(n);
   if (ptr == NULL)
       fatal("Out of memory");
   return ptr;

}

void* xrealloc(void* p, size_t n) {

   void* ptr = realloc(p, n);
   if (ptr == NULL)
       fatal("Out of memory");
   return ptr;

}

int word_compare(const void* p1, const void* p2) {

   return memcmp(p1, p2, WORD_SIZE);

}

int main(int argc, char** argv) {

   const char* filename = argc < 2 ? "unixdict.txt" : argv[1];
   FILE* in = fopen(filename, "r");
   if (!in) {
       perror(filename);
       return EXIT_FAILURE;
   }
   char line[MAX_WORD_SIZE];
   size_t size = 0, capacity = 1024;
   char* words = xmalloc(WORD_SIZE * capacity);
   while (fgets(line, sizeof(line), in)) {
       size_t len = strlen(line) - 1; // last character is newline
       if (len < MIN_LENGTH)
           continue;
       line[len] = '\0';
       if (size == capacity) {
           capacity *= 2;
           words = xrealloc(words, WORD_SIZE * capacity);
       }
       memcpy(&words[size * WORD_SIZE], line, WORD_SIZE);
       ++size;
   }
   fclose(in);
   qsort(words, size, WORD_SIZE, word_compare);
   int count = 0;
   char prev_word[WORD_SIZE] = { 0 };
   for (size_t i = 0; i + MIN_LENGTH <= size; ++i) {
       char word[WORD_SIZE] = { 0 };
       for (size_t j = 0; j < MIN_LENGTH; ++j)
           word[j] = words[(i + j) * WORD_SIZE + j];
       if (word_compare(word, prev_word) == 0)
           continue;
       if (bsearch(word, words, size, WORD_SIZE, word_compare))
           printf("%2d. %s\n", ++count, word);
       memcpy(prev_word, word, WORD_SIZE);
   }
   free(words);
   return EXIT_SUCCESS;

}</lang>

Output:
 1. applicate
 2. architect
 3. astronomy
 4. christine
 5. christoph
 6. committee
 7. composite
 8. constrict
 9. construct
10. different
11. extensive
12. greenwood
13. implement
14. improvise
15. intercept
16. interpret
17. interrupt
18. philosoph
19. prescript
20. receptive
21. telephone
22. transcend
23. transport
24. transpose

C++

<lang cpp>#include <algorithm>

  1. include <cstdlib>
  2. include <fstream>
  3. include <iomanip>
  4. include <iostream>
  5. include <string>
  6. include <vector>

int main(int argc, char** argv) {

   const int min_length = 9;
   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;
   }
   std::string line;
   std::vector<std::string> words;
   while (getline(in, line)) {
       if (line.size() >= min_length)
           words.push_back(line);
   }
   std::sort(words.begin(), words.end());
   std::string previous_word;
   int count = 0;
   for (size_t i = 0, n = words.size(); i + min_length <= n; ++i) {
       std::string word;
       word.reserve(min_length);
       for (size_t j = 0; j < min_length; ++j)
           word += words[i + j][j];
       if (previous_word == word)
           continue;
       auto w = std::lower_bound(words.begin(), words.end(), word);
       if (w != words.end() && *w == word)
           std::cout << std::setw(2) << ++count << ". " << word << '\n';
       previous_word = word;
   }
   return EXIT_SUCCESS;

}</lang>

Output:
 1. applicate
 2. architect
 3. astronomy
 4. christine
 5. christoph
 6. committee
 7. composite
 8. constrict
 9. construct
10. different
11. extensive
12. greenwood
13. implement
14. improvise
15. intercept
16. interpret
17. interrupt
18. philosoph
19. prescript
20. receptive
21. telephone
22. transcend
23. transport
24. transpose

Delphi

Translation of: Java

<lang Delphi> program Words_from_neighbour_ones;

{$APPTYPE CONSOLE}

uses

 System.SysUtils,
 System.Classes;

function GetWords(minLength: Integer = 1): TStringList; var

 i: Integer;

begin

 Result := TStringList.create;
 Result.LoadFromFile('Unixdict.txt');
 with Result do
   for i := Count - 1 downto 0 do
     if Strings[i].Length < minLength then
       Delete(i);
 Result.Sort;

end;

var

 Words: TStringList;

const

 minLength = 9;

begin

 Words := GetWords(minLength);
 var previousWord := ;
 var count := 0;
 var n := Words.Count;
 for var i := 0 to n - minLength do
 begin
   var W := ;
   for var j := 0 to minLength - 1 do
     W := W + Words[i + j][j + 1];
   if W.Equals(previousWord) then
     Continue;
   if Words.IndexOf(W) >= 0 then
   begin
     inc(count);
     writeln(count: 2, '. ', W);
   end;
   previousWord := W;
 end;
 Words.Free;
 readln;

end.</lang>

Output:
 1. applicate
 2. architect
 3. astronomy
 4. christine
 5. christoph
 6. committee
 7. composite
 8. constrict
 9. construct
10. different
11. extensive
12. greenwood
13. implement
14. improvise
15. intercept
16. interpret
17. interrupt
18. philosoph
19. prescript
20. receptive
21. telephone
22. transcend
23. transport
24. transpose

F#

<lang fsharp> // Words from neighbour ones. Nigel Galloway: February 11th., 2021. let g=[|use n=System.IO.File.OpenText("unixdict.txt") in while not n.EndOfStream do yield n.ReadLine()|]|>Array.filter(fun n->n.Length>8) g|>Array.windowed 9|>Array.map(fun n->n|>Array.mapi(fun n g->g.[n])|>System.String)|>Array.filter(fun n-> Array.contains n g)|>Array.distinct|>Array.iter(printfn "%s") </lang>

Output:
applicate
architect
astronomy
christine
christoph
committee
composite
constrict
construct
different
extensive
greenwood
implement
improvise
intercept
interpret
interrupt
philosoph
prescript
receptive
telephone
transcend
transport
transpose

Factor

{ "abc" "def" "ghi" } 2 clump produces { { "abc" "def" } { "def" "ghi" } }. <clumps> is the same idea except it doesn't actually store all that redundant information in memory; it's a generator that generates clumps on demand. Notice that clumps are matrices, so we can take their diagonal with main-diagonal.

Works with: Factor version 0.99 2020-08-14

<lang factor>USING: formatting grouping hash-sets io.encodings.ascii io.files kernel literals math math.matrices sequences sequences.extras sets strings ;

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

CONSTANT: wordset $[ words >hash-set ]

words  ! place word list on data stack [ length 9 < ] reject  ! remove small words from list 9 <clumps>  ! create virtual sequence of every 9 adjacent words (overlapping) [ main-diagonal >string ]  ! map clump to its diagonal [ wordset in? ] map-filter  ! filter diagonals that are words members  ! remove duplicates [ 1 + swap "%2d. %s\n" printf ] each-index  ! print words formatted nicely</lang>

Output:
 1. applicate
 2. architect
 3. astronomy
 4. christine
 5. christoph
 6. committee
 7. composite
 8. constrict
 9. construct
10. different
11. extensive
12. greenwood
13. implement
14. improvise
15. intercept
16. interpret
17. interrupt
18. philosoph
19. prescript
20. receptive
21. telephone
22. transcend
23. transport
24. transpose


FreeBASIC

Translation of: Ring

<lang freebasic> Open "unixdict.txt" For Input As #1 Dim As String cStr, wordList() Dim As Integer n, p = 0, posic = 0 Do While Not Eof(1)

   Line Input #1, cStr
   p += 1
   If Len(cStr) > 8 Then
       posic += 1
       Redim Preserve wordList(posic)
       wordList(posic) = cStr
   End If

Loop Close #1

Print p; " palabras en el archivo de diccionario: unixdict.txt" Print Ubound(wordList); " palabras utilizables en el archivo del diccionario."

Dim As String char(1 To 9), palabra Dim As String nextwords(Ubound(wordList))

Print !"\ntrabajando...\n" Print !"Las nuevas palabras son:\n"

posic = 0 For n = 1 To Ubound(wordList)-8

   palabra = ""
   For p = 1 To 9
       char(p) = Mid(wordList(n+p-1),p,1)
       palabra += char(p)
   Next p
   
   For p = 1 To Ubound(wordList)
       If wordList(p) = palabra Then
           posic += 1
           nextwords(posic) = palabra
       End If
   Next p

Next n

posic = 0 For n = 2 To Ubound(nextwords)

   If nextwords(n) <> nextwords(n-1) Then
       posic += 1
       Print ""; posic; ". "; nextwords(n-1)
   End If

Next n

Print !"\nterminado..." Sleep </lang>

Output:
 25104 palabras en el archivo de diccionario: unixdict.txt
 7250 palabras utilizables en el archivo del diccionario.

trabajando...

Las nuevas palabras son:

 1. applicate
 2. architect
 3. astronomy
 4. christine
 5. christoph
 6. committee
 7. composite
 8. constrict
 9. construct
 10. different
 11. extensive
 12. greenwood
 13. implement
 14. improvise
 15. intercept
 16. interpret
 17. interrupt
 18. philosoph
 19. prescript
 20. receptive
 21. telephone
 22. transcend
 23. transport
 24. transpose

terminado...


Go

<lang go>package main

import (

   "bytes"
   "fmt"
   "io/ioutil"
   "log"
   "sort"
   "strings"
   "unicode/utf8"

)

func main() {

   wordList := "unixdict.txt"
   b, err := ioutil.ReadFile(wordList)
   if err != nil {
       log.Fatal("Error reading file")
   }
   bwords := bytes.Fields(b)
   var words []string
   for _, bword := range bwords {
       s := string(bword)
       if utf8.RuneCountInString(s) >= 9 {
           words = append(words, s)
       }
   }
   count := 0
   var alreadyFound []string
   le := len(words)
   var sb strings.Builder
   for i := 0; i < le-9; i++ {
       sb.Reset()
       for j := i; j < i+9; j++ {
           sb.WriteByte(words[j][j-i])
       }
       word := sb.String()
       ix := sort.SearchStrings(words, word)
       if ix < le && word == words[ix] {
           ix2 := sort.SearchStrings(alreadyFound, word)
           if ix2 == len(alreadyFound) {
               count++
               fmt.Printf("%2d: %s\n", count, word)
               alreadyFound = append(alreadyFound, word)
           }
       }
   }

}</lang>

Output:
 1: applicate
 2: architect
 3: astronomy
 4: christine
 5: christoph
 6: committee
 7: composite
 8: constrict
 9: construct
10: different
11: extensive
12: greenwood
13: implement
14: improvise
15: intercept
16: interpret
17: interrupt
18: philosoph
19: prescript
20: receptive
21: telephone
22: transcend
23: transport
24: transpose

Java

<lang java>import java.io.*; import java.util.*;

public class NeighbourWords {

   public static void main(String[] args) {
       try {
           int minLength = 9;
           List<String> words = new ArrayList<>();
           try (BufferedReader reader = new BufferedReader(new FileReader("unixdict.txt"))) {
               String line;
               while ((line = reader.readLine()) != null) {
                   if (line.length() >= minLength)
                       words.add(line);
               }
           }
           Collections.sort(words);
           String previousWord = null;
           int count = 0;
           for (int i = 0, n = words.size(); i + minLength <= n; ++i) {
               StringBuilder sb = new StringBuilder(minLength);
               for (int j = 0; j < minLength; ++j)
                   sb.append(words.get(i + j).charAt(j));
               String word = sb.toString();
               if (word.equals(previousWord))
                   continue;
               if (Collections.binarySearch(words, word) >= 0)
                   System.out.printf("%2d. %s\n", ++count, word);
               previousWord = word;
           }
       } catch (Exception e)  {
           e.printStackTrace();
       }
   }

}</lang>

Output:
 1. applicate
 2. architect
 3. astronomy
 4. christine
 5. christoph
 6. committee
 7. composite
 8. constrict
 9. construct
10. different
11. extensive
12. greenwood
13. implement
14. improvise
15. intercept
16. interpret
17. interrupt
18. philosoph
19. prescript
20. receptive
21. telephone
22. transcend
23. transport
24. transpose

JavaScript

<lang javascript> document.write(`

Choose dictionary: <input id="dict" type="file">

Word length: <input id="wlen" type="number" value="9"

`);

function go(dict) {

 let wordLen = parseInt(document.getElementById('wlen').value),
     result = [];
 dict = dict.replace(/\n|\r/g, '_');
 dict = dict.replace(/__/g, ' ').split(' ');
 dict = dict.filter(e => e.length >= wordLen);
 for (let i = 0; i < dict.length - wordLen; i++) {
   let word = dict[i][0];
   for (let j = 1; j < wordLen; j++) {
     word += dict[i+j][j];
   }
   if (dict.includes(word) && !result.includes(word)) result.push(word);
 }
 document.getElementById('out').innerText = result.join(', ');

}

document.getElementById('dict').onchange = function() {

 let f = document.getElementById('dict').files[0],
     fr = new FileReader();
 fr.onload = function() { go(fr.result) }
 fr.readAsText(f);

} </lang>

Output:
applicate, architect, astronomy, christine, christoph, committee, composite, constrict, construct, different, extensive, greenwood, implement, improvise, intercept, interpret, interrupt, philosoph, prescript, receptive, telephone, transcend, transport, transpose

jq

For speed, this solution constructs a JSON object as a dictionary ($hash):<lang jq>

  1. input: the dictionary
  2. $n: starting point (starting at 0)

def form_word($n):

  . as $dict
  | reduce range(0;9) as $i (""; . + $dict[$n+$i][$i: $i+1] );

[inputs | select(length >= 9)] | . as $dict | (reduce.[] as $x ({}; .[$x]=true)) as $hash | range(0; length-9) as $i | form_word($i) | select($hash[.])</lang>

Output:
["applicate","architect","astronomy","christine","christoph","committee","committee","committee","committee","committee","composite","constrict","constrict","construct","different","extensive","greenwood","implement","improvise","intercept","interpret","interrupt","interrupt","philosoph","prescript","receptive","telephone","transcend","transcend","transport","transpose"]

Removing duplicates efficiently

Using `def form_word`, we have only to modify the last line above: <lang jq>[inputs | select(length >= 9)] | . as $dict | (reduce.[] as $x ({}; .[$x]=true)) as $hash | reduce range(0; length-9) as $i ({$hash};

      ($dict | form_word($i)) as $w
      | if .hash[$w] then .hash[$w] = null | .words += [$w] else . end)

| .words</lang>

Julia

<lang julia>function wordsfromneighbourones(wordfile::String, len = 9, colwidth = 11, numcols = 8)

   println("Word source: $wordfile\n")
   words = filter(w -> length(w) >= len, split(read(wordfile, String), r"\s+"))
   dict, shown, found = Dict(w => 1 for w in words), 0, String[]
   for position in eachindex(@view words[1:end-len+1])
       new_word = prod([words[i + position - 1][i] for i in 1:len])
       if haskey(dict, new_word) && !(new_word in found)
           push!(found, new_word)
           print(rpad(new_word, colwidth), (shown += 1) % numcols == 0 ? "\n" : "")
       end
   end

end

wordsfromneighbourones("unixdict.txt")

</lang>

Output:
Word source: unixdict.txt

applicate  architect  astronomy  christine  christoph  committee  composite  constrict
construct  different  extensive  greenwood  implement  improvise  intercept  interpret
interrupt  philosoph  prescript  receptive  telephone  transcend  transport  transpose

Ksh

<lang ksh>

  1. !/bin/ksh
  1. Words from neighbour ones
  1. # Variables:

dict='/home/ostrande/prj/roscode/unixdict.txt' integer MIN_WORD_LEN=9 TRUE=1 FALSE=0

typeset -a word newword integer i j=0

  1. # Functions:
  2. # Function _buildword(arr) - build MIN_WORD_LEN word from arr eles

function _buildword { typeset _arr ; nameref _arr="$1" typeset _indx ; integer _indx=$2 typeset _i _str ; integer _i

for ((_i=0; _i<MIN_WORD_LEN; _i++)); do _str+=${_arr[$((_indx+_i))]:${_i}:1} done echo "${_str}" }

  1. # Function _isword(word, wordlist) - return 1 if word in wordlist

function _isword { typeset _word ; _word="$1" typeset _wordlist ; nameref _wordlist="$2"

[[ ${_word} == @(${_wordlist}) ]] && return $TRUE return $FALSE }

######
  1. main #
######

while read; do (( ${#REPLY} >= MIN_WORD_LEN )) && word+=( $REPLY ) done < ${dict} oldIFS="$IFS" ; IFS='|' ; words=${word[*]} ; IFS="${oldIFS}"

for ((i=0; i<${#word[*]}; i++)); do candidate=$(_buildword word ${i}) _isword "${candidate}" words if (( $? )); then if [[ ${candidate} != @(${uniq%\|*}) ]]; then print $((++j)) ${candidate} uniq+="${candidate}|" fi fi done</lang>

Output:

1 applicate 2 architect 3 astronomy 4 christine 5 christoph 6 committee 7 composite 8 constrict 9 construct 10 different 11 extensive 12 greenwood 13 implement 14 improvise 15 intercept 16 interpret 17 interrupt 18 philosoph 19 prescript 20 receptive 21 telephone 22 transcend 23 transport

24 transpose

Lua

<lang lua>wordlist, wordhash = {}, {} for word in io.open("unixdict.txt", "r"):lines() do

 if #word >= 9 then
   wordlist[#wordlist+1] = word
   wordhash[word] = #wordlist
 end

end for n = 1, #wordlist-8 do

 local word = ""
 for i = 0, 8 do
   word = word .. wordlist[n+i]:sub(i+1,i+1)
 end
 if wordhash[word] then
   -- task appears to say "for every n, do all of the following"
   -- but doesn't appear to say "..unless a duplicate"
   -- so, intentionally verbose/redundant:
   print(word)
 end

end</lang>

Output:
applicate
architect
astronomy
christine
christoph
committee
committee
committee
committee
committee
composite
constrict
constrict
construct
different
extensive
greenwood
implement
improvise
intercept
interpret
interrupt
interrupt
philosoph
prescript
receptive
telephone
transcend
transcend
transport
transpose

Mathematica/Wolfram Language

<lang Mathematica>dict = Once[Import["https://web.archive.org/web/20180611003215/http://www.puzzlers.org/pub/wordlists/unixdict.txt"]]; dict //= StringSplit[#,"\n"]&; dict //= Select[StringLength/*GreaterEqualThan[9]]; firsts9 = Characters[dict]All,;;9; words = StringJoin[Diagonal[firsts9,-#]]&/@Range[0,Length[firsts9]-9]; Intersection[words,dict]</lang>

Output:
{"applicate", "architect", "astronomy", "christine", "christoph", "committee", "composite", "constrict", "construct", "different", "extensive", "greenwood", "implement", "improvise", "intercept", "interpret", "interrupt", "philosoph", "prescript", "receptive", "telephone", "transcend", "transport", "transpose"}

Nim

<lang Nim>import sets, strutils, sugar

  1. Build list and set of words with length >= 9.

let words = collect(newSeq):

             for word in "unixdict.txt".lines:
               if word.len >= 9: word

let wordSet = words.toHashSet

var lastWord = "" var newWord = newString(9) var count = 0 for i in 0..words.high-9:

 for j in 0..8: newWord[j] = words[i+j][j]
 if newWord in wordSet:
   if newWord != lastWord:
     inc count
     echo ($count).align(2), ' ', newWord
     lastWord = newWord</lang>
Output:
 1 applicate
 2 architect
 3 astronomy
 4 christine
 5 christoph
 6 committee
 7 composite
 8 constrict
 9 construct
10 different
11 extensive
12 greenwood
13 implement
14 improvise
15 intercept
16 interpret
17 interrupt
18 philosoph
19 prescript
20 receptive
21 telephone
22 transcend
23 transport
24 transpose

Perl

<lang perl>#!/usr/bin/perl

use strict; # https://rosettacode.org/wiki/Words_from_neighbour_ones use warnings;

@ARGV = 'unixdict.txt'; my $skew = join , map { s/^.{9}\K.+//r } my @words = grep length() > 9, <>; my %dict = map { $_ => 1 } grep length == 10, @words; my %seen; my $nextch = '.{10}(\\w)' x 8; while( $skew =~ /^(\w)(?=$nextch)/gms )

 {
 my $new = join , @{^CAPTURE}, "\n";
 $dict{$new} and !$seen{$new}++ and print $new;
 }</lang>
Output:

applicate architect astronomy christine christoph committee composite constrict construct different extensive greenwood implement improvise intercept interpret interrupt philosoph prescript receptive telephone transcend transport transpose

Phix

with javascript_semantics
function over9(string word) return length(word)>=9 end function
sequence words = filter(unix_dict(),over9)
function slicen(integer n) return vslice(words,n)[n..-10+n] end function
sequence neighwords = unique(filter(columnize(apply(tagset(9),slicen)),"in",words))
printf(1,"%d words: %s\n",{length(neighwords),join(shorten(neighwords,"",3))})
Output:
24 words: applicate architect astronomy ... transcend transport transpose

Processing

<lang Processing>StringList words = new StringList(), found = new StringList(); for (String str : loadStrings("unixdict.txt")) {

 if (str.length() >= 9) {
   words.append(str);
 }

} for (int i = 0; i < words.size() - 9; i++) {

 String temp = "";
 for (int j = 0; j < 9; j++) {
   temp += words.get(i + j).charAt(j);
 }
 if (words.hasValue(temp) && !found.hasValue(temp)) {
   found.append(temp);
 }

} for (String word : found) {

 println(word);

}</lang>

Output:
applicate
architect
astronomy
christine
christoph
committee
composite
constrict
construct
different
extensive
greenwood
implement
improvise
intercept
interpret
interrupt
philosoph
prescript
receptive
telephone
transcend
transport
transpose


Python

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. <lang Python>

  1. Aamrun, 5th November 2021

import urllib.request from collections import Counter

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()

filteredWords = [chosenWord for chosenWord in wordList if len(chosenWord)>=9]

for word in filteredWords[:-9]:

 position = filteredWords.index(word)
 newWord = "".join([filteredWords[position+i][i] for i in range(0,9)])
 if newWord in filteredWords:
  print(newWord)  

</lang>

Output:

Yes, there are duplicates, the task doesn't say that only unique elements should be present, hence the complete raw list will appear as below :

applicate
architect
astronomy
christine
christoph
committee
committee
committee
committee
committee
composite
constrict
constrict
construct
different
extensive
greenwood
implement
improvise
intercept
interpret
interrupt
interrupt
philosoph
prescript
receptive
telephone
transcend
transcend
transport
transpose

Raku

<lang perl6>my @words_ge_9 = 'unixdict.txt'.IO.lines.grep( *.chars >= 9 ); my %words_eq_9 = @words_ge_9 .grep( *.chars == 9 ).Set;

my @new_words = gather for @words_ge_9.rotor( 9 => -8 ) -> @nine_words {

   my $new_word = [~] map { @nine_words[$_].substr($_, 1) }, ^9;
   take $new_word if %words_eq_9{$new_word};

}

.say for unique @new_words;</lang>

Output:
applicate
architect
astronomy
christine
christoph
committee
composite
constrict
construct
different
extensive
greenwood
implement
improvise
intercept
interpret
interrupt
philosoph
prescript
receptive
telephone
transcend
transport
transpose

REXX

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 the words is   caseless.

It also allows the minimum length to be specified on the command line (CL) as well as the dictionary file identifier. <lang rexx>/*REXX pgm finds words that're composed from neighbor words (within an identified dict).*/ parse arg minL iFID . /*obtain optional arguments from the CL*/ if minL== | minL=="," then minL= 9 /*Not specified? Then use the default.*/ if iFID== | iFID=="," then iFID='unixdict.txt' /* " " " " " " */

  1. = 0; @.=;  !.= 0 /*number of usable words in dictionary.*/
           do recs=0  while lines(iFID)\==0     /*read each word in the file  (word=X).*/
           x= strip( linein( iFID) )            /*pick off a word from the input line. */
           if length(x)<minL  then iterate      /*Is the word too short?  Then skip it.*/
           #= # + 1                             /*bump the count of usable words.      */
           @.#= x;       upper x;      !.x= 1   /*original case;  create findable word.*/
           end   /*recs*/                       /* [↑]   semaphore name is uppercased. */

say copies('─', 30) recs "words in the dictionary file: " iFID say copies('─', 30) right(#, length(recs) ) "usable words in the dictionary file." finds= 0 /*count of the changable words found.*/ say; $=

       do j=1  for #;           y= left(@.j, 1) /*initialize the new word to be built. */
            do k=2  to 9  until n>#;   n= j + k /*use next 8 usable words in dictionary*/
            y= y || substr(@.n, k, 1)           /*build a new word, 1 letter at a time.*/
            end   /*k*/
       uy=y;                    upper uy        /*obtain uppercase version of the word.*/
       if \!.uy  then iterate                   /*Does the new word exist?  No, skip it*/
       if wordpos(uy, $)>0  then iterate        /*Word is a dup?  Then skip duplicate. */
       finds= finds + 1                         /*bump count of found neighboring words*/
       $= $ uy                                  /*add a word to the list of words found*/
       say right( left(y, 30), 40)              /*indent original word for readability.*/
       end      /*j*/
                                                /*stick a fork in it,  we're all done. */

say copies('─', 30) finds ' neighbor words found with a minimum length of ' minL</lang>

output   when using the default inputs:
────────────────────────────── 25104 words in the dictionary file:  unixdict.txt
──────────────────────────────  7250 usable words in the dictionary file.

          applicate
          architect
          astronomy
          christine
          christoph
          committee
          composite
          constrict
          construct
          different
          extensive
          greenwood
          implement
          improvise
          intercept
          interpret
          interrupt
          philosoph
          prescript
          receptive
          telephone
          transcend
          transport
          transpose
────────────────────────────── 24  neighbor words found with a minimum length of  9

Ring

<lang ring> cStr = read("unixdict.txt") wordList = str2list(cStr) char = list(9) nextwords = [] num = 0

see "working..." + nl

ln = len(wordList) for n = ln to 1 step -1

   if len(wordList[n]) < 9
      del(wordList,n)
   ok

next

see "New words are:" + nl

for n = 1 to len(wordList)-8

   for m = 1 to 9
       char[m] = substr(wordList[n+m-1],m,1)
   next
   str = ""
   for p = 1 to 9
       str = str + char[p]
   next
   ind = find(wordList,str)
   if ind > 0
      add(nextwords,wordList[ind])
   ok

next

nextwords = sort(nextwords) for n = len(nextwords) to 2 step -1

   if nextwords[n] = nextwords[n-1]
      del(nextwords,n)
   ok

next

for n = 1 to len(nextwords)

   see "" + n + ". " + nextwords[n] + nl

next

see "done..." + nl </lang> Output:

working...
New words are:
1. applicate
2. architect
3. astronomy
4. christine
5. christoph
6. committee
7. composite
8. constrict
9. construct
10. different
11. extensive
12. greenwood
13. implement
14. improvise
15. intercept
16. interpret
17. interrupt
18. philosoph
19. prescript
20. receptive
21. telephone
22. transcend
23. transport
24. transpose
done...

Wren

Library: Wren-sort
Library: Wren-fmt

<lang ecmascript>import "io" for File import "/sort" for Find import "/fmt" for Fmt

var wordList = "unixdict.txt" // local copy var words = File.read(wordList).trimEnd().split("\n").where { |w| w.count >= 9 }.toList var count = 0 var alreadyFound = [] for (i in 0...words.count - 9) {

   var word = ""
   for (j in i...i+9) word = word + words[j][j-i]
   if (Find.all(words, word)[0] && !Find.all(alreadyFound, word)[0]) {
       count = count + 1
       Fmt.print("$2d: $s", count, word)
       alreadyFound.add(word)
   }

}</lang>

Output:
 1: applicate
 2: architect
 3: astronomy
 4: christine
 5: christoph
 6: committee
 7: composite
 8: constrict
 9: construct
10: different
11: extensive
12: greenwood
13: implement
14: improvise
15: intercept
16: interpret
17: interrupt
18: philosoph
19: prescript
20: receptive
21: telephone
22: transcend
23: transport
24: transpose

XPL0

<lang 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>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 DI, I, Ch, Count; char Word, Neigh(10), Last(10); def LF=$0A, CR=$0D, EOF=$1A;

[FSet(FOpen("unixdict.txt", 0), ^I); \load dictionary OpenI(3); \assume alphabetical order and all lowercase DI:= 0; 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;
               ];
       if I >= 9 then                  \ignore words less than 9 characters
               [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; Last(0):= 0; repeat for I:= 0 to 9-1 do \build Neigh word using letters from

           [Word:= Dict(DI+I);         \ following words
           Neigh(I):= Word(I);
           ];
       Neigh(9):= 0;                   \terminate string
       if LookUp(Neigh) then           \if it's a word and not already listed
           if StrCmp(Neigh, Last) # 0 then
               [CopyMem(Last, Neigh, 10);
               Count:= Count+1;
               Text(0, Neigh);
               if rem(Count/8) = 0 then CrLf(0) else ChOut(0, ^ );
               ];
       DI:= DI+1;                      \next word in dictionary

until DI >= DictSize-9; CrLf(0); ]</lang>

Output:
applicate architect astronomy christine christoph committee composite constrict
construct different extensive greenwood implement improvise intercept interpret
interrupt philosoph prescript receptive telephone transcend transport transpose

Yabasic

Translation of: FreeBASIC

<lang yabasic> open "unixdict.txt" for reading as #1 p = 0 posic = 0 while not eof(1)

   line input #1 cStr$
   p = p + 1
   if len(cStr$) > 8 then
       posic = posic + 1
       redim wordList$(posic)
       wordList$(posic) = cStr$
   end if

wend close #1

print p, " palabras en el archivo de diccionario: unixdict.txt" print arraysize(wordList$(), 1), " palabras utilizables en el archivo del diccionario."

dim char$(9) dim nextwords$(arraysize(wordList$(), 1))

print chr$(10), "trabajando...", chr$(10)

print "Las nuevas palabras son:", chr$(10)

posic = 0 for n = 1 to arraysize(wordList$(), 1) - 8

   palabra$ = ""
   for p = 1 to 9
       char$(p) = mid$(wordList$(n + p - 1), p, 1)
       palabra$ = palabra$ + char$(p)
   next p
   
   for p = 1 to arraysize(wordList$(), 1)
       if wordList$(p) = palabra$ then
           posic = posic + 1
           nextwords$(posic) = palabra$
       end if
   next p

next n

posic = 0 for n = 2 to arraysize(nextwords$(), 1)

   if nextwords$(n) <> nextwords$(n - 1) then
       posic = posic + 1
       print "", posic, ". ", nextwords$(n - 1)
   end if

next n end </lang>

Output:
Igual que la entrada de FreeBASIC.