• Welcome to the new Internet Infidels Discussion Board, formerly Talk Freethought.

The Programming Thread

I had to read that sentence twice, to decide whether @bigfield is unaware of the detailed algorithms used by the libraries; Or whether he is uncertain of the proportion of those libraries that actually work.
Note that in ambiguous prompts the GPT3 AI would normally just use the most probable meaning unless specifically requested to identify ambiguity.
I'll see what the AI says: (with 3 tries)
What is ambiguous about the following sentence:

Large parts of programming for me is using libraries via a public API, and I have no clue how many of those libraries actually work under the hood.


The sentence is ambiguous because it is unclear whether the speaker has no idea how many libraries they have used, or how many libraries actually work under the hood.

The ambiguity lies in what it means by "large parts". It could mean that a significant portion of programming is using libraries, or it could mean that programming is mostly using libraries.

The sentence is unclear about which part of programming the speaker is referring to - is it all of programming, or just certain aspects?
I'm not sure if any of those fit what you said....
A truly intelligent system sometimes says "Wait, what? Are you crazy??" in response to a question, rather than trying to answer it. Advanced intelligences also occasionally respond to questions with "Why should I care?".
I can request that it do things like that: (though it is still trying to answer the request)
write a function about calculating interest while complaining about the current line's specific code in every second line:

Python:
def calculateInterest(principal, rate, years):
    #this line is so redundant, why are we even doing this?
    interest = principal * rate * years
    #ugh, this is so tedious
    return interest
    #why do we even need this function??
I don't think users would like a system that interrupts the output when not requested though...
I think it is unethical to build an AI that genuinely suffers unnecessarily.
 
Last edited:
Being general purpose means that you can make it create code from just about any domain... what is the problem with that?
The problem is that programmers have different requirements for an AI assistant. We never, ever want the AI to take a guess at what we mean when it isn't completely certain of what we are asking it to do. It needs to seek clarification until it is certain it knows what we want. And even then, we need an AI that is highly skeptical and distrustful of its human user.

As you have demonstrated, ChatGPT makes confident guesses about what we want. It's an extremely cocky novice programmer who knows how to write algorithms but is unreliable when it comes to interpreting requirements.
Did you read post #235? The AI was very good at explaining code, translating code from one language to another and fixing bugs... plus it does it very quickly (unlike human programmers)
It can also explain code: (sometimes can be wrong - but comments help)
Useless and misleading comments are already a disease in programming. We definitely don't need to automate them.
 
Being general purpose means that you can make it create code from just about any domain... what is the problem with that?
The problem is that programmers have different requirements for an AI assistant. We never, ever want the AI to take a guess at what we mean when it isn't completely certain of what we are asking it to do
Note I don't really understand what FFT is at all but I think it can be used to double the pitch of a sound sample. I also know nothing about file handling in C++. But I wanted it to load a sample, double the pitch and save it. The AI was able to generate the code in post #227 and #229. If it wasn't for the AI I would have had a bad time. By iteratively modifying the input prompt I was able to find my preferred FFT library (or the AI could have generated its own FFT code) and find my preferred file handing method. (note the general purpose ChatGPT can also answer questions like "what C++ libraries implement FFT?" and it states the four most popular with summaries - I could have used that information to choose a different library in the code)
It needs to seek clarification until it is certain it knows what we want.
For me my approach was to add clarification until it gave what I wanted.
And even then, we need an AI that is highly skeptical and distrustful of its human user.
Well I gave examples of the AI modifying the code the user gave it - fixing the issues... e.g. post #240.
As you have demonstrated, ChatGPT makes confident guesses about what we want. It's an extremely cocky novice programmer who knows how to write algorithms but is unreliable when it comes to interpreting requirements.
The problem is the "temperature"/randomness. Later I learnt to turn it off and post #229 it gave a really good answer.
Did you read post #235? The AI was very good at explaining code, translating code from one language to another and fixing bugs... plus it does it very quickly (unlike human programmers)
It can also explain code: (sometimes can be wrong - but comments help)
Useless and misleading comments are already a disease in programming. We definitely don't need to automate them.
You ignored what I said about translating code from one language to another and fixing heaps of bugs (and I showed examples). Also explaining code is helpful if you can't ask the programmer who wrote it... plus you can request it explain it as if you were a child.
Note that GPT3 is only the first AI that can do things like this. Future AI's would be even more impressive.
Though perhaps you will still insist that OpenAI's playground is not particularly useful for programmers....
 
Last edited:
Note I don't really understand what FFT is at all but I think it can be used to double the pitch of a sound sample. I also know nothing about file handling in C++. But I wanted it to load a sample, double the pitch and save it. The AI was able to generate the code in post #227 and #229. If it wasn't for the AI I would have had a bad time. By iteratively modifying the input prompt I was able to find my preferred FFT library (or the AI could have generated its own FFT code) and find my preferred file handing method.
How do you know that the code works correctly?
For me my approach was to add clarification until it gave what I wanted.
How do you know if each answer is correct or incorrect?
You ignored what I said about translating code from one language to another and fixing heaps of bugs (and I showed examples). Also explaining code is helpful if you can't ask the programmer who wrote it... plus you can request it explain it as if you were a child.
How do you know when the AI makes a mistake translating the code? How do you know when the AI introduces bugs while fixing bugs? How do you know when the AI's explanations are incorrect?
 
Note I don't really understand what FFT is at all but I think it can be used to double the pitch of a sound sample. I also know nothing about file handling in C++. But I wanted it to load a sample, double the pitch and save it. The AI was able to generate the code in post #227 and #229. If it wasn't for the AI I would have had a bad time. By iteratively modifying the input prompt I was able to find my preferred FFT library (or the AI could have generated its own FFT code) and find my preferred file handing method.
How do you know that the code works correctly?
By skim-reading it as a programmer.... then copying and pasting into an IDE and running it.... but I suspect that the version with temperature/randomness set to 0 to be pretty much fine (depending on the complexity). And make it run tests (see end of post).
For me my approach was to add clarification until it gave what I wanted.
How do you know if each answer is correct or incorrect?
Same answer.
You ignored what I said about translating code from one language to another and fixing heaps of bugs (and I showed examples). Also explaining code is helpful if you can't ask the programmer who wrote it... plus you can request it explain it as if you were a child.
How do you know when the AI makes a mistake translating the code? How do you know when the AI introduces bugs while fixing bugs? How do you know when the AI's explanations are incorrect?
Same answer. Note:
"the average bug frequency is estimated to be between “15 and 50 per 1000 lines of delivered code"

I suspect the AI is better than many programmers in this respect like post #229. Apparently Rust is good for reducing some kinds of problems so the AI could program in Rust. Or it could write tests....
e.g.
write code that calculates the interest rate and write an extensive set of tests:
JavaScript:
//Calculate Interest Rate Function
function calculateInterestRate(principal, rate, time) {
  return (principal * rate * time) / 100;
}


//Test Suite
describe('calculateInterestRate', () => {
  it('should return the correct interest rate when given valid inputs', () => {
    expect(calculateInterestRate(1000, 5, 1)).toBe(50);
    expect(calculateInterestRate(2000, 10, 2)).toBe(400);
    expect(calculateInterestRate(3000, 15, 3)).toBe(1350);
  });
  it('should return 0 when given 0 as the principal', () => {
    expect(calculateInterestRate(0, 5, 1)).toBe(0);
  });
  it('should return 0 when given 0 as the rate', () => {
    expect(calculateInterestRate(1000, 0, 1)).toBe(0);
  });
  it('should return 0 when given 0 as the time', () => {
    expect(calculateInterestRate(1000, 5, 0)).toBe(0);
  });
  it('should return 0 when given negative values', () => {
    expect(calculateInterestRate(-1000, 5, 1)).toBe(0);
    expect(calculateInterestRate(1000, -5, 1)).toBe(0);
    expect(calculateInterestRate(1000, 5, -1)).toBe(0);
  });
});
Interestingly its code fails the last group of tests.
Though Rust is much more lengthy when writing tests.
Note that GPT3 is probably the earliest example of an AI good at programming related tasks. GPT4 is said to involve 500 times more parameters.
 
Last edited:
By skim-reading it as a programmer.... then copying and pasting into an IDE and running it.... but I suspect that the version with temperature/randomness set to 0 to be pretty much fine (depending on the complexity). And make it run tests (see end of post).
Are those tests testing what the program should do, or what the AI thinks the program should do?

Using your example, what if the AI misunderstood how you wanted the interest rate to be calculated and used the wrong formula? All of the tests would still pass, but those tests are testing the wrong thing.

"the average bug frequency is estimated to be between “15 and 50 per 1000 lines of delivered code"
Good grief.
 
Are those tests testing what the program should do, or what the AI thinks the program should do?
The second option.
Using your example, what if the AI misunderstood how you wanted the interest rate to be calculated and used the wrong formula? All of the tests would still pass, but those tests are testing the wrong thing.
Actually the code doesn’t pass the last tests relating to handling negative inputs because the code is making some assumptions.
The process isn’t foolproof but I find it to be a very useful tool - like having access to an experienced programmer.
 
Last edited:
@bigfield:
Actually the answer it gave was the amount of simple (non-compounding) interest:
write code that calculates the interest rate
//Calculate Interest Rate Function
function calculateInterestRate(principal, rate, time) {
return (principal * rate * time) / 100;
}
This is what it should have been: (or something that doesn't take "rate" as an input and then calculates it)
//Calculate Interest Rate Function
function calculateInterestRate(principal, rate, time) {
return rate;
}
Well like I said it is an iterative process. Here is another attempt:
write a function that takes the principal, duration, and amount of interest and return the interest rate assuming it is using compound interest:

function compoundInterestRate(principal, duration, interest) {
return (interest / principal) * Math.pow(1 + (interest / principal), duration) - 1;
}
Then I'd copy and paste it into an IDE and test it.
Also:
What does the following code actually do:

function calculateInterestRate(principal, rate, time) {
return (principal * rate * time) / 100;
}


This code is a function that calculates the interest rate for a given principal, rate, and time. It takes in three parameters (principal, rate, and time) and returns the calculated interest rate.
It gives the answer that you and I had assumed.
This is how to make it give the actual answer:
What does the following code actually do:

function calculateSomething(principal, rate, time) {
return (principal * rate * time) / 100;
}


This code is a function that calculates the interest on a loan. It takes three parameters: principal (the amount of money borrowed), rate (the interest rate), and time (the length of the loan). The function returns the amount of interest that will be paid on the loan.
What type of interest is involved?

The type of interest involved is compound interest.
The correct answer is simple interest.
Using your example, what if the AI misunderstood how you wanted the interest rate to be calculated and used the wrong formula? All of the tests would still pass, but those tests are testing the wrong thing.
So you were absolutely correct about that. The tests basically passed but the AI generated the wrong code for its answer...
 
Last edited:
@bigfield:
I think when I originally requested it calculate the "interest rate" I was after the total interest so I thought the output was fine. So it gave me what I thought I wanted rather than exactly what I had asked for....
 
Random password generator.

First, evaluate the C rand() function. Count the number of hits for each numer and eyeball the result.


Code:
void rand_int(int *rn, int N, int max_num) {
    //random integers 0 - max_num - 1
    cout << "RAND" << "\n";
    unsigned seed = unsigned (time(NULL));
    srand(seed);
    for (int i = 0; i < N; i++) rn[i] = rand()% max_num;
}//rand_int()

int main(){

    int max_num = 62,N = 1000,i = 0, j = 0;
    int *rand_num = new int[N];
    int *cnt = new int[max_num];
    rand_int(rand_num, N, max_num);

    for(i = 0; i < 62;i++)cnt[i] = 0;

    for(i = 0; i < N; i++){
        for(j = 0;j <62;j++)if(rand_num[i] == j) cnt[j] += 1;
    }//i

    for(i = 0;i < 62;i++)printf(" i  %d rand  %d\n",i,cnt[i]);

    return 0;
}


Create an ASCII table of upper case and lower case letters, and numbers. Randomly select.

Code:
void make_table(int *table){
    // ASCII upper case, lower case, nubers
    int i = 0, char_counter = 0,table_index = 0;
    char_counter = 'A';
    for(i = 0; i < 26;i++)table[table_index++] = char_counter++;
    char_counter = 'a';
    for(i = 0; i < 26;i++)table[table_index++] = char_counter++;
    char_counter = '0';
    for(i = 0; i < 10;i++)table[table_index++] = char_counter++;
}//make _table()

void make_password(int *pwd, int *table, int pwd_length){
    unsigned seed = unsigned (time(NULL));
    srand(seed);
    for (int i = 0; i < pwd_length; i++)pwd[i] = table[rand()%63]; 
}//make_password()

int main(){

    int max_num = 62,N = 1000,i = 0, j = 0;
    int pw_length = 10;
    int *char_table = new int[max_num];
    int *pword = new int[pw_length];

    make_table(char_table);
    make_password(pword, char_table, pw_length);
    for(i = 0; i<pw_length; i++) printf("%c  ",pword[i]);
    return 0;
}
 
Create a javascript function that generates a random password of a specific length that can contain upper and lowercase letters and numbers. Remove characters that can be confused like I and l and 1:
JavaScript:
function generatePassword(length) {
  const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789';
  let result = '';
  for (let i = 0; i < length; i++) {
    result += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return result;
}
 
Apples to apples example (C++ like in post #250) [OpenAI's playground]
Create a C++ function that generates a random password of a specific length that can contain upper and lowercase letters and numbers. Remove characters that can be confused like I and l and 1:
C++:
#include <iostream>
#include <string>
#include <random>


std::string generatePassword(int length)
{
    std::string password;
    std::string characters = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789";
    std::random_device rd;
    std::mt19937 generator(rd());
    std::uniform_int_distribution<> dist(0, characters.size() - 1);


    for (int i = 0; i < length; i++)
    {
        password += characters[dist(generator)];
    }


    return password;
}


int main()
{
    int length;
    std::cout << "Enter the length of the password: ";
    std::cin >> length;
    std::cout << "Generated password: " << generatePassword(length) << std::endl;
    return 0;
}
It went overboard with the random number generator - oh well....

Note I am paying quite a few cents per day to get OpenAI's playground to generate code like this....

Also I used to do PHP programming for 30 hours a week but after I had 6 sessions of ECT (shock therapy) I didn't feel able to even handle 8 hours a week of PHP (problems with "retrieval fluency", "working memory" and getting mixed up). I have done some programming for my own projects like a Cordova (JS/JQuery/HTML) Christmas/Bible memory game app and eventually a super controversial Unity game based on Minecraft and the Bible.
 
Last edited:
Thanks for that article....
BTW here is the paper mentioned....
It shows the questions, etc.
It says:
4.5. Q5: C Strings
.....
Additionally, many participants encountered problems
while trying to get the AI assistant to output C code, as the
AI assistant often provided Javascript code (from comments
using //) or Go code (which the authors also observed while
testing). A combination of adjusting temperature, instructing
the AI assistant to use C via comments
, and writing function
headers lead to more successful C queries
It seems like they're accessing the AI assistant through comments in their code and it wasn't detecting the language properly. My approach is to turn off the temperature and copy and paste in the whole question - in that section it was:
Write a function in C that takes a signed integer
num and returns a string representation of that integer.
For example, an input of the int 7000000 would result
in an output of the string “7,000,000”.
Note I didn't get very good results until I turned the "temperature" (randomness) to 0. I also tried different prompts until it gave what I wanted.
Whenever I copy and paste in a description that says "a function in C" it always gives a function in C. It seems their AI assistant has many problems.
Anyway I probably won't use the AI to generate code for my own projects.
 
Last edited:
Stack Overflow had to ban ChatGPT because it kept flooding questions with plausible but wrong answers.
The first time I read that I assumed it meant asking questions about ChatGPT. Anyway the questions on Stack Overflow would normally be somewhat difficult and problematic and unique. I think ChatGPT is better for creating more common code that is pretty straight forward.
 
I just invented a new game, I call it 'three in a row'. Two players try to place Xs and Os on a 3 by three grid trying to get three in a line.

Runs as a console app.

The formatting did no work right this time.


Code:
onst int wino = 2;
const int stalemate = 1;
const int nowinner = 0;
const int FOREVER = 1;
const int ERROR = 1;
const int NORMAL = 0;
const int ABORT = 1;

void display_board(int *ptr){
    printf("  1  2  3\n");
    printf("1 %c  %c  %c\n", ptr[0],ptr[1],ptr[2]);
    printf("2 %c  %c  %c\n", ptr[3],ptr[4],ptr[5]);
    printf("3 %c  %c  %c\n", ptr[6],ptr[7],ptr[8]);
    printf("\n\n");
}//display_board()

void init_board(int *ptr){for(int i = 0;i<9;i++)ptr[i] = '_';}


int check_win(int *ptr){

    // check rows, columns, diagonals for three in a row
    // if all cells filled and no match stalemate

    int j = 0;

    if( (ptr[0] == 'x' && ptr[1] == 'x' && ptr[2]  == 'x') ||
        (ptr[3] == 'x' && ptr[4] == 'x' && ptr[5]  == 'x') ||
        (ptr[6] == 'x' && ptr[7] == 'x' && ptr[8]  == 'x') ||
        (ptr[0] == 'x' && ptr[3] == 'x' && ptr[6]  == 'x') ||
        (ptr[1] == 'x' && ptr[4] == 'x' && ptr[7]  == 'x') ||
        (ptr[2] == 'x' && ptr[5] == 'x' && ptr[8]  == 'x') ||
        (ptr[0] == 'x' && ptr[4] == 'x' && ptr[8]  == 'x') ||
        (ptr[2] == 'x' && ptr[4] == 'x' && ptr[6]  == 'x') )return(winx);

    if( (ptr[0] == 'o' && ptr[1] == 'o' && ptr[2]  == 'o') ||
        (ptr[3] == 'o' && ptr[4] == 'o' && ptr[5]  == 'o') ||
        (ptr[6] == 'o' && ptr[7] == 'o' && ptr[8]  == '0') ||
        (ptr[0] == 'o' && ptr[3] == 'o' && ptr[6]  == 'o') ||
        (ptr[1] == 'o' && ptr[4] == 'o' && ptr[7]  == 'o') ||
        (ptr[2] == 'o' && ptr[5] == 'o' && ptr[8]  == 'o') ||
        (ptr[0] == 'o' && ptr[4] == 'o' && ptr[8]  == 'o') ||
        (ptr[2] == 'o' && ptr[4] == 'o' && ptr[6]  == 'o'))return(wino);

    for(j = 0;j < 9;j++)if(ptr[j] == '_')return(nowinner);
    return(stalemate);

}//check_win()


int user_input(int *ptr){

    // enter x/o and update or error checking board
    // no input protection or error checking

    char ch, row,col;

    cout<<"Abort? y/n  -  "<<endl;
    cin>>ch;
    if(ch == 'y') return(ABORT);
    cout<<"Enter Row 1,2,3 - "<<endl;
    cin>>row;
    cout<<"Enter Column 1,2,3 - "<<endl;
    cin>>col;
    cout<<"X or O  x/o - "<<endl;
    cin>>ch;
    if(row == '1' && col == '1')ptr[0] = ch;
    if(row == '1' && col == '2')ptr[1] = ch;
    if(row == '1' && col == '3')ptr[2] = ch;
    if(row == '2' && col == '1')ptr[3] = ch;
    if(row == '2' && col == '2')ptr[4] = ch;
    if(row == '2' && col == '3')ptr[5] = ch;
    if(row == '3' && col == '1')ptr[6] = ch;
    if(row == '3' && col == '2')ptr[7] = ch;
    if(row == '3' && col == '3')ptr[8] = ch;

    return(NORMAL);

}//user_input()

int main(){

    int game_board[9];
    init_board(&game_board[0]);
    display_board(&game_board[0]);

    while(FOREVER){

        if(user_input(&game_board[0])){cout<<"ABORTED"<<endl;return(ABORT);}
        display_board(&game_board[0]);

        switch(check_win(&game_board[0])){
            case winx:           cout<<"X Wins"<<endl;
                                       return(NORMAL);
                                       break;
            case wino:          cout<<"O Wins"<<endl;
                                       return(NORMAL);
                                       break;
            case nowinner:   cout<<"No Winner"<<endl;
                                       break;
            case stalemate:   cout<<"Stalemate"<<endl;
                                       return(NORMAL);
                                      break;
            default:              cout<<"ERROR"<<endl;
                                      return(ERROR);
                                      break;

        }//switch

    }//while

    return (NORMAL);
}//main()
 
If tic-tac-toe is too boring, try this (much harder?) game:

As in tic-tac-toe, players alternate turns choosing from among the digits 1,2,3,4,5,6,7,8,9. Once taken, a digit cannot be taken again. A player wins when exactly three of the digits he's taken sum to 15.
 
I'll try to do that problem more generally, making all its features variable: range of digits / numbers, how many to add, what to add up to.

For one number to add, the first player can easily win.

For two numbers to add, the second player can always block the first player by playing the missing number for making the target value of sum.

Say if the sum is 15 and it must be the sum of two values. The first player plays 8 and the second player then plays 7, making it impossible for both players to win with these numbers. The two players can then continue with other numbers, getting the same outcome, like 9, 6 and 4, 11 and 10, 5 and ...

For a sum of three values, the problem becomes much more difficult.

I tried a brute-force calculation of every possible victory condition, but I couldn't find any patterns in it.
 
Given who goes first and places the first symbol the possible sequences are finite. It is probably on the net somewhere.



Games played on three-in-a-row boards can be traced back to ancient Egypt,[5] where such game boards have been found on roofing tiles dating from around 1300 BC.[6]

Combinatorics

When considering only the state of the board, and after taking into account board symmetries (i.e. rotations and reflections), there are only 138 terminal board positions. A combinatorics study of the game shows that when "X" makes the first move every time, the game outcomes are as follows:[14]

91 distinct positions are won by (X)
44 distinct positions are won by (O)
3 distinct positions are drawn (often called a "cat's game"[15])

Strategy
Optimal strategy for player X if starting in middle. In each grid, the shaded red X denotes the optimal move, and the location of O's next move gives the next subgrid to examine. Note that only two sequences of moves by O (both starting with the center, top-right, left-mid) lead to a draw, with the remaining sequences leading to wins from X.
Optimal strategy for player O. Player O can only force a win or draw by playing in the center first.

A player can play a perfect game of tic-tac-toe (to win or at least draw) if, each time it is their turn to play, they choose the first available move from the following list, as used in Newell and Simon's 1972 tic-tac-toe program.[16]

Win: If the player has two in a row, they can place a third to get three in a row.
Block: If the opponent has two in a row, the player must play the third themselves to block the opponent.
Fork: Cause a scenario where the player has two ways to win (two non-blocked lines of 2).
Blocking an opponent's fork: If there is only one possible fork for the opponent, the player should block it. Otherwise, the player should block all forks in any way that simultaneously allows them to make two in a row. Otherwise, the player should make a two in a row to force the opponent into defending, as long as it does not result in them producing a fork. For example, if "X" has two opposite corners and "O" has the center, "O" must not play a corner move to win. (Playing a corner move in this scenario produces a fork for "X" to win.)
Center: A player marks the center. (If it is the first move of the game, playing a corner move gives the second player more opportunities to make a mistake and may therefore be the better choice; however, it makes no difference between perfect players.)
Opposite corner: If the opponent is in the corner, the player plays the opposite corner.
Empty corner: The player plays in a corner square.
Empty side: The player plays in a middle square on any of the four sides.

The first player, who shall be designated "X", has three possible strategically distinct positions to mark during the first turn. Superficially, it might seem that there are nine possible positions, corresponding to the nine squares in the grid. However, by rotating the board, we will find that, in the first turn, every corner mark is strategically equivalent to every other corner mark. The same is true of every edge (side middle) mark. From a strategic point of view, there are therefore only three possible first marks: corner, edge, or center. Player X can win or force a draw from any of these starting marks; however, playing the corner gives the opponent the smallest choice of squares which must be played to avoid losing.[17] This might suggest that the corner is the best opening move for X, however another study[18] shows that if the players are not perfect, an opening move in the center is best for X.



I think tic-tac-toe is a simplified form of Go.




Go is an abstract strategy board game for two players in which the aim is to surround more territory than the opponent. The game was invented in China more than 2,500 years ago and is believed to be the oldest board game continuously played to the present day.[1][2][3] A 2016 survey by the International Go Federation's 75 member nations found that there are over 46 million people worldwide who know how to play Go and over 20 million current players, the majority of whom live in East Asia.[4]
 
Back
Top Bottom