g | x | w | all
Bytes Lang Time Link
560Wolfram LanguageMathematica250921T052332Z138 Aspe
099JavaScript Node.js240924T050859Ztsh
113JavaScript ES6240923T103031ZArnauld
075Charcoal240923T235437ZNeil
356Python3240923T184659ZAjax1234
03005AB1E240923T095642ZKevin Cr

Wolfram Language(Mathematica), 560 bytes

560 bytes, it can be golfed more.


Golfed version. Try it online!

S[a_]:=If[StringQ[a],a,StringJoin[S[Last[#]]&/@a]]
P[a_,b_]:=Flatten[F[a,b,0]]
F[a_,b_,c_]:=Module[{r={},d=c},If[StringQ[a],Return[{}]];Do[With[{i=e[[1]],v=e[[2]]},If[i==b,AppendTo[r,d]];If[StringQ[v],d+=StringLength[v],Module[{s=F[v,b,d]},r=Join[r,s];d+=StringLength[S[v]]]]],{e,a}];r]
B[a_]:=Module[{b={{0,"a"},{1,"b"}},c=1},While[c+1<=a,c++;AppendTo[b,{c,Take[b,-2]}]];b]
H[a_,b_,c_]:=Module[{d,e,f,g,h},d=B[a];e=Association[Rule@@@d];f=P[e[a],b];If[MemberQ[f,c],Return[2]];g=S[e[a]];h=S[e[b]];If[StringLength[g]>c&&StringStartsQ[StringDrop[g,c],h],1,Null]]

Ungolfed version. Try it online!

(* Helper function to check if a value is a string *)
isStringQ[value_] := StringQ[value]

(* Recursively flatten a nested structure to a string *)
flattenToString[structure_] := 
  If[isStringQ[structure], 
    structure,
    StringJoin[flattenToString[Last[#]] & /@ structure]
  ]

(* Find all positions where targetIndex appears in the structure *)
(* Returns a list of positions in the flattened string *)
findPositions[structure_, targetIndex_] := 
  Module[{},
    Flatten[findPositionsHelper[structure, targetIndex, 0]]
  ]

findPositionsHelper[structure_, targetIndex_, currentPos_] := 
  Module[{results = {}, pos = currentPos},
    If[isStringQ[structure], 
      Return[{}] (* No positions found in a string *)
    ];
    
    (* Process each element in the structure *)
    Do[
      With[{index = element[[1]], content = element[[2]]},
        (* If this element's index matches our target, record the current position *)
        If[index == targetIndex, 
          AppendTo[results, pos]
        ];
        
        (* Move position forward based on the content *)
        If[isStringQ[content],
          (* If content is a string, advance position by its length *)
          pos += StringLength[content],
          (* If content is a structure, recursively find positions and advance *)
          Module[{subResults = findPositionsHelper[content, targetIndex, pos]},
            results = Join[results, subResults];
            (* Advance position by the total length of the flattened subcontent *)
            pos += StringLength[flattenToString[content]];
          ]
        ]
      ],
      {element, structure}
    ];
    
    results
  ]

(* Build Fibonacci-like sequence structure *)
buildFibonacciStructure[n_] := 
  Module[{sequence, currentIndex},
    sequence = {{0, "a"}, {1, "b"}};
    currentIndex = 1;
    
    While[currentIndex + 1 <= n,
      currentIndex++;
      AppendTo[sequence, {currentIndex, Take[sequence, -2]}]
    ];
    
    sequence
  ]

(* Main function to check Fibonacci pattern *)
checkFibonacciPattern[N_, n_, offset_] := 
  Module[{fibonacciSequence, fibonacciAssociation, positionsOfN, flattenedN, flattenedN2},
    (* Build Fibonacci-like sequence structure *)
    fibonacciSequence = buildFibonacciStructure[N];
    fibonacciAssociation = Association[Rule @@@ fibonacciSequence];
    
    (* Check if offset matches any position where target index n appears in structure N *)
    positionsOfN = findPositions[fibonacciAssociation[N], n];
    
    If[MemberQ[positionsOfN, offset],
      Return[2] (* regular pattern *)
    ];
    
    (* Check if the flattened string from N starting at offset begins with flattened string of n *)
    flattenedN = flattenToString[fibonacciAssociation[N]];
    flattenedN2 = flattenToString[fibonacciAssociation[n]];
    
    If[StringLength[flattenedN] > offset && 
       StringStartsQ[StringDrop[flattenedN, offset], flattenedN2],
      Return[1], (* strange pattern *)
      Return[Null] (* wrong pattern *)
    ]
  ]

(* Test data *)
testCases = {
  {4, 0, 0, "regular"},
  {4, 0, 1, "wrong"},
  {4, 0, 2, "wrong"},
  {4, 0, 3, "regular"},
  {4, 0, 4, "wrong"},
  {5, 0, 0, "wrong"},
  {5, 0, 1, "regular"},
  {5, 0, 2, "wrong"},
  {5, 0, 3, "regular"},
  {5, 0, 4, "wrong"},
  {5, 0, 5, "wrong"},
  {5, 0, 6, "regular"},
  {5, 0, 7, "wrong"},
  {4, 1, 0, "wrong"},
  {4, 1, 1, "regular"},
  {4, 1, 2, "regular"},
  {4, 1, 3, "wrong"},
  {4, 1, 4, "regular"},
  {5, 1, 0, "regular"},
  {5, 1, 1, "wrong"},
  {5, 1, 2, "regular"},
  {5, 1, 3, "wrong"},
  {5, 1, 4, "regular"},
  {5, 1, 5, "regular"},
  {5, 1, 6, "wrong"},
  {5, 1, 7, "regular"},
  {1, 0, 0, "wrong"},
  {10, 2, 7, "wrong"},
  {7, 3, 0, "regular"},
  {7, 3, 7, "strange"},
  {7, 3, 9, "wrong"},
  {7, 3, 10, "regular"},
  {7, 3, 11, "wrong"},
  {14, 7, 47, "strange"},
  {14, 7, 479, "strange"},
  {14, 7, 335, "strange"},
  {14, 7, 335, "strange"},
  {14, 7, 369, "strange"},
  {14, 7, 513, "strange"},
  {14, 7, 100, "wrong"},
  {14, 7, 200, "wrong"},
  {14, 7, 300, "wrong"},
  {14, 7, 13, "regular"},
  {14, 7, 123, "regular"},
  {14, 7, 233, "regular"},
  {14, 7, 322, "regular"}
};

(* Expected result mapping *)
expectedResults = <|
  "regular" -> 2,
  "strange" -> 1,
  "wrong" -> Null
|>;


(* Run tests *)
Print["\n=== RUNNING TESTS ==="];

testResults = Table[
  With[{N = testCase[[1]], n = testCase[[2]], offset = testCase[[3]], expected = testCase[[4]]},
    Module[{result = checkFibonacciPattern[N, n, offset]},
      {
        testCase,
        result,
        expectedResults[expected],
        result === expectedResults[expected]
      }
    ]
  ],
  {testCase, testCases}
];

(* Check if all tests passed *)
allTestsPassed = AllTrue[testResults, Last];

If[allTestsPassed,
  Print["All tests passed!"],
  Print["Some tests failed:"];
  failedTests = Select[testResults, Not[Last[#]] &];
  Print["Number of failed tests: ", Length[failedTests]];
  Print["First few failed tests:"];
  Take[failedTests, Min[5, Length[failedTests]]] // TableForm // Print
];

JavaScript (Node.js), 99 bytes

(N,n,o)=>[0,n].map(k=>(F=n=>('ab'[n]||F(n-2)+F(n-1)).replace(/./,n-k&&'$&'))(N).indexOf(F(n),o)==o)

Try it online!

Output [true,true] for regular, [true,false] for strange, [false,false] for wrong.


Let's denote \$x\#y\$ as string concatenation, and \$x\left[1:\right]\$ as string slicing which remove the first letter from \$x\$.

$$ F(x)=\begin{cases} \textbf{a}&x=0\\ \textbf{b}&x=1\\ F(x-2)\#F(x-1)&x>1 \end{cases} $$

$$ G(x)=\begin{cases} F(x)&x\le 1\wedge x\ne n\\ G(x-2)\#G(x-1)&x>1\wedge x\ne n\\ \textbf{c}\#F(x)\left[1:\right]&x=n \end{cases} $$

I have no idea how to prove its correctness, it simply passed all testcases. Any prove or bad cases are welcomed.

JavaScript (ES6), 113 bytes

Expects (N)(n)(o) and returns false for strange, true for regular, 2 for wrong.

N=>n=>g=(o,x,y=(U="toUpperCase")[+!x])=>~N--?g(o,n--?y:y=p=y[U](),x&&x+y):(s=x.substr(o,p.length))[U]()==p?s==p:2

Try it online!

Method

We recursively build all patterns \$F_0\$ to \$F_N\$ using letters in lower case (ironically using the 'o' and 't' from the string 'toUpperCase' for golfing reasons).

When \$F_n\$ is reached, we convert it to upper case, save it in \$p\$ and use the transformed string for the recursion. All subsequent regular occurrences of \$p\$ will therefore appear in upper case as well.

At the end of the process, we look for \$p\$ at offset \$o\$ in \$F_N\$:

Commented

N => n =>             // outer functions taking N and n
g = (                 // inner recursive function taking:
  o,                  //   the offset o
  x,                  //   a string x (initially undefined)
  y = (               //   a string y initialized by using the
    U = "toUpperCase" //   first 2 characters of "toUpperCase":
  )[+!x]              //   - "o" if x is undefined (1st iteration)
                      //   - "t" if x is defined (2nd iteration)
) =>                  //
~N-- ?                // if N != -1 (decrement afterwards):
  g(                  //   do a recursive call:
    o,                //     pass o unchanged
    n-- ?             //     if n != 0 (decrement afterwards):
      y               //       use y unchanged
    :                 //     else:
      y = p = y[U](), //       update y and p to y in upper case
    x && x + y        //     if x is defined, pass x + y
                      //     (pass undefined otherwise)
  )                   //   end of recursive call
:                     // else:
  (                   //
    s = x.substr(     //   s = relevant slice of x
      o, p.length     //       at offset o and of size p.length
    )                 //
  )[U]() == p ?       //   if s in upper case is equal to p:
    s == p            //     compare s with p (Boolean value)
  :                   //   else:
    2                 //     return 2 for 'wrong'

Charcoal, 75 bytes

NθNηNζFab⊞υιFθ⊞υ⭆²§υ⁻λ²I∧№⌕A§υθ§υηζ⊕∨‹η²№E⌕A§υ⊕⁻θηbΣE²×№…§υ⊕⁻θηι§υλL§υ⁻η¬λζ

Try it online! Link is to verbose version of code. Outputs 0 for wrong, 1 for strange and 2 for regular. Explanation:

NθNηNζ

Input N, n and o.

Fab⊞υιFθ⊞υ⭆²§υ⁻λ²

Generate the first N+2 Fibonacci words.

I∧№⌕A§υθ§υηζ

If o is not one of the places where the nth word appears in the Nth word, then the output is 0.

⊕∨‹η²

If n<2 then the output is 2.

№E⌕A§υ⊕⁻θηbΣE²×№…§υ⊕⁻θηι§υλL§υ⁻η¬λζ

Otherwise, the Nth word is composed of copies of the n-1th and nth words, given by the N-n+1th word, where an a in that word represents a copy of the n-1th word and a b in that word represents a copy of the nth word. Using the lengths of the n-1th and nth words, generate the offsets inside the Nth word corresponding to all of the bs which represent all of the regular nth subwords, and check whether o is one of those.

Python3, 356 bytes

I=lambda a:isinstance(a,str)
T=lambda a:a if I(a)else''.join(T(b)for _,b in a)
def O(t,n,C):
 if I(t):return
 for a,b in t:
  if a==n:yield C[0]
  if I(b):C[0]+=len(b)
  else:yield from O(b,n,C)
def f(N,n,o):
 k=[(0,'a'),(t:=1,'b')]
 while(t:=t+1)<=N:k+=[(t,k[-2:])]
 K=dict(k)
 if o in[*O(K[N],n,[0])]:return 2
 if T(K[N])[o:].startswith(T(K[n])):return 1

Try it online!

05AB1E, 30 bytes

1ÝλN¹›i‚»ë«]¹I‚è`IF¦¶Û}Dþ‚sδÅ?

Inputs in the order \$n,N,o\$. Outputs [1,1] for regular; [0,1] for strange; and [0,0] for wrong.

Try it online or verify all test cases.

Explanation:

  λ        # Create a recursive environment,
           # to output the infinite sequence
1Ý         # Starting with a(0)=0 and a(1)=1
           # Where every following a(x) is calculated as:
           #  (implicitly push the previous terms a(x-2) and a(x-1))
   N¹›i    #  If x is larger than first input `n`:
       ‚   #   Pair the two previous terms: [a(x-2),a(x-1)]
        »  #   Join this pair with newline-delimiter
      ë    #  Else:
       «   #   Append term a(x-1) to a(x-2) instead
  ]        # Close both the if-statement and recursive environment
   ¹I‚     # Push a pair of the first two inputs: [n,N]
      è    # (0-based) index those into the infinite list
`          # Pop and push both separated to the stack
 IF        # Loop the third input `o` amount of times:
   ¦       #  Remove the first bit
    ¶Û     #  And also trim a potential leading newline character
  }D       # After the loop: duplicate the off-set result
    þ      # Remove all newlines from the copy, by only keeping digits
     ‚     # Pair the two together
       δ   # Map over this pair:
      s Å? #  Check for both whether it starts with the n'th term
           # (after which this pair is output implicitly as result)