' knn_classifier.pb — K-Nearest Neighbors classifier
#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN() AS LONG
    LOCAL trainX(100) AS DOUBLE
    LOCAL trainY(100) AS DOUBLE
    LOCAL trainLabels(100) AS LONG
    LOCAL distances(100) AS DOUBLE
    LOCAL distLabels(100) AS LONG
    LOCAL numTrain AS LONG
    LOCAL numTests AS LONG
    LOCAL kVal AS LONG
    LOCAL i AS LONG
    LOCAL j AS LONG
    LOCAL t AS LONG
    LOCAL x AS LONG
    LOCAL testX AS DOUBLE
    LOCAL testY AS DOUBLE
    LOCAL expectedLabel AS LONG
    LOCAL predictedLabel AS LONG
    LOCAL distVal AS DOUBLE
    LOCAL dx AS DOUBLE
    LOCAL dy AS DOUBLE
    LOCAL minDist AS DOUBLE
    LOCAL minIdx AS LONG
    LOCAL vote0 AS LONG
    LOCAL vote1 AS LONG
    LOCAL correct AS LONG
    LOCAL incorrect AS LONG
    LOCAL sortDone AS LONG
    LOCAL tempDist AS DOUBLE
    LOCAL tempLabel AS LONG
    LOCAL iter AS LONG
    LOCAL sampleIdx AS LONG

    numTrain = 12
    numTests = 6
    kVal = 3

    PRINT "=== K-Nearest Neighbors ==="
    PRINT "Training: " + STR$(numTrain) + " Test: " + STR$(numTests) + " K=" + STR$(kVal)

    FOR i = 0 TO numTrain - 1
        trainX(i) = i * 5 + (i MOD 4) * 2
        trainY(i) = i * 3 + (i MOD 3) * 5
        IF i < numTrain / 2 THEN
            trainLabels(i) = 0
        ELSE
            trainLabels(i) = 1
        END IF
    NEXT i

    FOR sampleIdx = 0 TO numTests - 1
        testX = 10 + sampleIdx * 7
        testY = 5 + sampleIdx * 9

        IF sampleIdx < 3 THEN
            expectedLabel = 0
        ELSE
            expectedLabel = 1
        END IF

        FOR i = 0 TO numTrain - 1
            dx = testX - trainX(i)
            dy = testY - trainY(i)
            distVal = dx * dx + dy * dy
            distances(i) = distVal
            distLabels(i) = trainLabels(i)
        NEXT i

        sortDone = 0
        WHILE 1
            sortDone = 1
            FOR i = 0 TO numTrain - 2
                IF distances(i) > distances(i + 1) THEN
                    tempDist = distances(i)
                    distances(i) = distances(i + 1)
                    distances(i + 1) = tempDist
                    tempLabel = distLabels(i)
                    distLabels(i) = distLabels(i + 1)
                    distLabels(i + 1) = tempLabel
                    sortDone = 0
                END IF
            NEXT i
            IF sortDone = 1 THEN EXIT LOOP
        WEND

        vote0 = 0
        vote1 = 0
        FOR i = 0 TO kVal - 1
            IF distLabels(i) = 0 THEN vote0 = vote0 + 1
            IF distLabels(i) = 1 THEN vote1 = vote1 + 1
        NEXT i

        IF vote0 > vote1 THEN
            predictedLabel = 0
        ELSE
            predictedLabel = 1
        END IF

        IF predictedLabel = expectedLabel THEN
            correct = correct + 1
        ELSE
            incorrect = incorrect + 1
        END IF

        PRINT "  Sample " + STR$(sampleIdx) + ": predicted=" + STR$(predictedLabel) + " expected=" + STR$(expectedLabel)
    NEXT sampleIdx

    PRINT "Correct: " + STR$(correct) + "/" + STR$(numTests)
    PRINT "Accuracy: " + STR$(correct * 100 / numTests) + "%"
    PRINT "=== End KNN ==="
    FUNCTION = 0
END FUNCTION
