100 SEO Tips for Beginner

100 SEO Tips for Beginner

[​IMG]

– Top 100 tips for SEO
– SEO on Website, Blogs , e-commerce , Products
– This eBook will give you 100 search engine techniques.
– The competition is fierce in the search engines.

…​

100 SEO Tips for Beginner

web hosting – Which Laravel 8 CMS to learn as Beginner?

I’m learning web development and need to provide a simple CMS for a customer, with which he can manage his website. For now creating posts on his website is all he needs.

There seem to be a ton of CMS packages for Laravel. Which one would you recommend for me to learn?

Also: Some packages seem to require an initial setup and can’t be integrated in existing projects. For flexibility’s sake I’d prefer if a package can be integrated in an existing project, should the need arise.

beginner – Cloud storage using python Socket library

One year ago I learned some Python 3 in Highschool, but I haven’t really programmed anything since then. I decided to start a new project to try and practice a bit before entering the first year of an IT degree. I tried to create my own cloud storage system in a console application using the Socket library, i.e. a program which can send file to a server and retreive them later. I wrote both the client and the server script. It was intended to be only an exercise at first, but I may end up actually using it if I can make it good enough.

Since I wasn’t at all familiar with the Socket library, I based my code off of this tutorial, but I now think I’ve made the code different enough to call it my own.

I’ve put quite some time into this project and now that I got everything working, I’d really like some feedback. In particular, and in order of importance :

  • Did I pick up any bad habbits ?
  • Could I make this look cleaner, for exemple by modifing synthax, or adding or fusing fuctions ?
  • Is my commenting any good ? Should I comment more or less ? Is it clear enough ?
  • Is there any way to optimize the transfer ?

Of course, any criticism is good to take so any remark regarding anything is welcome.

Notes:

  • This program is meant to transfer file only and trying to download a directory from the server will cause an error. It is however a non-issue as you cannot select a directory to upload from the the client and the server’s storage directory should not contain anything that wasn’t sent by the client under normal circumstances.
    • If you decide to manually add files in the server’s storage directory, keep in mind that directories are not supported.
    • Modifying the content of the server’s storage directory after selecting the option to download files on the client and before you canceled the selection or all downloads are complete may result in an error
  • I will be the only person using this app so it isn’t useful to make it able to handle multiple requests at the same time.
  • Both the computers I use are connected to the same network.
  • The app has been tested and works on both Windows and Linux.
    • The client needs to run in an environment capable of showing a GUI as I use tkinter’s filedialog to select the files to send to the server. This not the case for the server.
  • I use python 3.8.2

Here is server script:

import socket
import tqdm
import os
import pickle
import sys

##Setup connection with client

#Set storage directory
workDir = "Insert path to server's storage directory"
os.chdir(workDir)

#Set global variable
SERVER_HOST = "0.0.0.0"
SERVER_PORT = 5001
BUFFER_SIZE = 1024
SEPARATOR = "<SEPARATOR>"

#Start listening for connection attempt and perform the action chosen by the client
def start_listening():
    #Accept the connexion of the client
    s = socket.socket()
    s.bind((SERVER_HOST, SERVER_PORT))
    s.listen(1)
    print(f"-------------------------nListening to {SERVER_HOST}:{SERVER_PORT}")
    client_socket, CLIENT_HOST = s.accept()
    print(f"{CLIENT_HOST} is connected.")

    #Perform the action chosen by the client
    actionID = client_socket.recv(BUFFER_SIZE).decode()
    client_socket.send('0'.encode())
    if actionID == '1':
        receive_file_choice(client_socket)
    if actionID == '2':
        send_file_choice(client_socket)
    if actionID == '3':
        client_socket.close()
        s.close()
        sys.exit()

    #Restart the script to perform another action
    client_socket.send('0'.encode())
    client_socket.close()
    s.close()
    start_listening()

##Download

#Receive the number, names and sizes of the files to download
def receive_file_choice(client_socket):
    fileNumber = int(client_socket.recv(BUFFER_SIZE).decode())
    client_socket.send('0'.encode())

    #Control the receive_file() function
    for i in range(fileNumber):
        received = client_socket.recv(BUFFER_SIZE).decode()
        fileName, fileSize = received.split(SEPARATOR)
        fileName = os.path.basename(fileName)
        fileSize = int(fileSize)
        client_socket.send('0'.encode())

        print(f"nDownloading {fileName} ({fileSize} bytes)")
        receive_file(client_socket, fileName, fileSize)

#Download the file sent by the client and store them in workDir
def receive_file(client_socket, fileName, fileSize):
    client_socket.send('0'.encode())

    with open(fileName, "wb") as f:

        downloadSize = 0
        timeOutFlag = 0
        #Setting a time out here ensure the the script can continue even if a packet was lost
        client_socket.settimeout(10)
        #Receive packets of size BUFFER_SIZE bytes
        for i in tqdm.tqdm(range(fileSize//BUFFER_SIZE)):
            try:
                downloadSize += f.write(client_socket.recv(BUFFER_SIZE))
            except (socket.timeout):
                print('Error : Download timed out')
                timeOutFlag = 1
                break
            #Tell the client it can send the next packet
            client_socket.send('0'.encode())
        #Receive remainig bytes
        if timeOutFlag == 0:
            try:
                downloadSize += f.write(client_socket.recv(fileSize%BUFFER_SIZE))
            except socket.timeout:
                pass
        client_socket.settimeout(None)

        #Warn the user if data has been lost during the transfer
        if downloadSize == fileSize:
            print("Done")
        else:
            print(f"Warning: '{fileName}' does not match expected sizen(Received {downloadSize} bytes instead of {fileSize} - {fileSize - downloadSize} bytes difference)")

    #Acknowledge that the download as ended. Send a '1' instead of '0' so that the client don't confuse it with the 'packet received' acknowledgement
    client_socket.send('1'.encode())

##Upload

#Send a list of available files and retreive client's choice
def send_file_choice(client_socket):
    print('Sending a list of available files to client')
    tempFileList = os.listdir(workDir)

    #If files are available to download for the client
    if len(tempFileList) >= 1:
        fileList = ((i, tempFileList(i), os.path.getsize(tempFileList(i))) for i in range(len(tempFileList)))
        sentFileList = pickle.dumps(fileList)

        client_socket.send(str(len(sentFileList)).encode())
        client_socket.recv(1)
        client_socket.send(sentFileList)
        print('Waiting for client response')


        choiceList = client_socket.recv(BUFFER_SIZE).decode()

        #Return if the client has chosen to cancel the download
        if choiceList.lower() == "-c":
            print('Request canceled')
            return

        choiceList = choiceList.split(',')
        client_socket.send('0'.encode())

        for i in range(len(choiceList)):
            choiceList(i) = int(choiceList(i))

        fileNumber = len(choiceList)
        client_socket.send(str(fileNumber).encode())
        client_socket.recv(1)

        control_upload(client_socket, fileList, choiceList)

    #Return if no file was found
    else:
        client_socket.send(pickle.dumps('0'))
        print('No file was found')
        return

#Operates the send_file() function
def control_upload(client_socket, fileList, choiceList):
    for i in choiceList:
        fileName, fileSize = fileList(i)(1), fileList(i)(2)
        client_socket.send(f"{fileName}{SEPARATOR}{fileSize}".encode())
        client_socket.recv(1)

        print(f"nUploading {fileName} ({fileSize} bytes)")
        send_file(client_socket, fileName, fileSize)

#Send requested file to the client
def send_file(client_socket, fileName, fileSize):
    client_socket.recv(1)

    with open(fileName, "rb") as f :

        #Upload the file divided in packet of size BUFFER_SIZE bytes
        for i in tqdm.tqdm(range(fileSize//BUFFER_SIZE)):
            bytes_read = f.read(BUFFER_SIZE)
            client_socket.sendall(bytes_read)
            client_socket.recv(1)
        #Send the remaining bytes
        bytes_read = f.read(fileSize%BUFFER_SIZE)
        client_socket.sendall(bytes_read)

        #Wait for the server to acknowledge it has ended downloading the file
        while True:
            if client_socket.recv(1).decode() == '1':
                break
        print("Done")

if __name__ == '__main__':
    start_listening()

Here is client script:

import tkinter as tk
from tkinter import filedialog
import os
import tqdm
import socket
import pickle
from time import sleep

##Set up connection with server

#Set storage directory
workDir = "Insert path to your download directory here"
os.chdir(workDir)

#Set global variables
SERVER_HOST = "Insert server's IP adress here"
SERVER_PORT = 5001
BUFFER_SIZE = 1024
SEPARATOR = "<SEPARATOR>"

#Start the connection with the server, choose the action to perfmorm
def start_connection():
    #Connect to the server
    s = socket.socket()
    print(f"-------------------------nConnecting to {SERVER_HOST}:{SERVER_PORT}")
    #Setting a timeout here prevent the client from trying to connect forever
    s.settimeout(30)
    try:
        s.connect((SERVER_HOST, SERVER_PORT))
    except socket.timeout:
        print("Error : Connection timed out")
        return
    #Maintaining the timeout past this point could cause an error if the user took a long time to decide what he want to do. timeout is therefore set to None.
    s.settimeout(None)
    print("Connected")

    #Ask for the user to choose the action to perform until he enter a valid action
    while True:
        actionID = input("nChoose action to perform:n1. Uploadn2. Downloadn3. Close servern4. Exitn-> ")
        if actionID in ('1','2','3','4'):
            break
        else:
            print('Invalid action')

    #Perform the requested action
    if actionID == '1':
        get_file_list(s)
    if actionID == '2':
        receive_file_choice(s)
    if actionID == '3':
        confirm = input("Do you want to procede? You won't be able to restart the server without physical access. (y/n)n-> ")
        if confirm == 'y' or confirm == 'Y':
            s.send('3'.encode())
            print("Server closed")
            return
        else:
            print("Server was not closed")
            return
    if actionID == '4':
        print('Exited')
        return

    #Restart the script to perform another action
    s.recv(1)
    sleep(0.2)
    s.close()
    start_connection()

##Upload

#Make the user choose the files to upload
def get_file_list(s):
    s.send('1'.encode())
    s.recv(1)

    #Open the file selection window
    selectionWindow = tk.Tk()
    selectionWindow.withdraw()

    fileNames = filedialog.askopenfilenames(parent=selectionWindow, initialdir=os.getcwd(), title='Please select file(s)')
    fileNumber = len(fileNames)
    fileSizes = tuple((os.path.getsize(fileNames(i)) for i in range(fileNumber)))

    selectionWindow.destroy()

    #Control the send_file() function
    s.send(str(fileNumber).encode())
    s.recv(1)
    for i in range(fileNumber):
        fileName, fileSize = fileNames(i), fileSizes(i)
        s.send(f"{fileName}{SEPARATOR}{fileSize}".encode())
        s.recv(1)

        print(f"nUploading {fileName} ({fileSize} bytes)")
        send_file(s, fileName, fileSize)

#Send a file to the server
def send_file(s, fileName, fileSize):
    s.recv(1)

    with open(fileName, "rb") as f :

        #Upload the file divided in packet of size BUFFER_SIZE bytes
        for i in tqdm.tqdm(range(fileSize//BUFFER_SIZE)):
            bytes_read = f.read(BUFFER_SIZE)
            s.sendall(bytes_read)
            s.recv(1)
        #Send the remaining bytes
        bytes_read = f.read(fileSize%BUFFER_SIZE)
        s.sendall(bytes_read)

        #Wait for the server to acknowledge it has ended downloading the file
        while True:
            if s.recv(1).decode() == '1':
                break
        print("Done")

##Download

#Ask for the user to choose the files to download
def receive_file_choice(s):
    s.send('2'.encode())
    s.recv(1)

    #Receive the list of all available files on the server
    print('Waiting for a list of available files')
    fileListSize = int(s.recv(BUFFER_SIZE).decode())
    s.send('0'.encode())
    sentFileList = s.recv(fileListSize)
    sentFileList = pickle.loads(sentFileList)

    #Return if no file is available
    if sentFileList == '0':
        print('No file is available')
        return

    else:
        print('nID ; Name ; Sizen----------------')

        possibleChoiceList = ()
        for i in range(len(sentFileList)):
            print(f"{sentFileList(i)(0)} ; {sentFileList(i)(1)} ; {sentFileList(i)(2)}")
            possibleChoiceList.append(str(sentFileList(i)(0)))

        #Ask for the user to chose file until a valid entry is given
        while True:
            choiceListStr = input('nEnter the IDs of the files to request separated with commasnEnter "-c" to canceln-> ')

            #Return if the user wants to cancel the download
            if choiceListStr.lower() == "-c":
                print('Request canceled')
                s.send(choiceListStr.encode())
                return

            choiceList = choiceListStr.split(',')
            #Check if the entry contains something that is not associated with a file (e.g., a negative number, a random letter...)
            if not set(choiceList).issubset(set(possibleChoiceList)):
                print('You cannot choose a file that is not listed')
            #Check if a file is requested twice
            elif len(choiceList) != len(set(choiceList)):
                print('You cannot choose a file more than once')
            #Break the loop if the entry is valid
            else:
                break

        s.send(choiceListStr.encode())
        s.recv(1)
        control_download(s)

#Operate the receive_file() function
def control_download(s):
    print('Waiting for the server to send files')
    fileNumber = s.recv(BUFFER_SIZE).decode()
    fileNumber = int(fileNumber)
    s.send('0'.encode())
    print(f"Downloading {fileNumber} files")

    for i in range(fileNumber):
        receive = s.recv(BUFFER_SIZE).decode()

        fileName, fileSize = receive.split(SEPARATOR)
        fileName = os.path.basename(fileName)
        fileSize = int(fileSize)

        s.send('0'.encode())

        print(f"nDownloading {fileName} ({fileSize} bytes)")
        receive_file(s, fileName, fileSize)

#Receive a file from the server and store it in workDir
def receive_file(s, fileName, fileSize):
    s.send('0'.encode())

    with open(fileName, "wb") as f:

        downloadSize = 0
        timeOutFlag = 0
        #Setting a timeout here ensure the the script can continue even if a packet was lost
        s.settimeout(10)
        #Receive packets of size BUFFER_SIZE bytes
        for i in tqdm.tqdm(range(fileSize//BUFFER_SIZE)):
            try:
                downloadSize += f.write(s.recv(BUFFER_SIZE))
            except socket.timeout :
                print("nError : Download timed out")
                timeOutFlag = 1
                break
            #Tell the server it can send the next packet
            s.send('0'.encode())
        #Receive the remainig bytes
        if timeOutFlag == 0:
            try:
                downloadSize += f.write(s.recv(fileSize%BUFFER_SIZE))
            except socket.timeout:
                pass
        s.settimeout(None)

        #Warn the user if data has been lost during the transfer
        if downloadSize == fileSize:
            print("Done")
        else:
            print(f"Warning: '{fileName}' does not match expected sizen(Received {downloadSize} bytes instead of {fileSize} - {fileSize - downloadSize} bytes difference)")

    #Acknowledge that the download as ended. Send a '1' instead of '0' so that the server don't confuse it with the 'packet received' acknowledgement
    s.send('1'.encode())

if __name__ == "__main__":
    start_connection()

When choosing the files to download on the client, you should see something like this

ID ; Name ; Size
----------------
0 ; 3tseT.txt ; 7
1 ; Script1.py ; 5102
2 ; Script2.py ; 4835
3 ; NicePDF.pdf ; 193721
4 ; Test1.txt ; 22
5 ; Test2.txt ; 16
6 ; Test3bis.txt ; 1

Enter the IDs of the files to request separated with commas
Enter "-c" to cancel
->

If you want to select the files 0, 1, 4 and 5, enter 0,1,4,5 in the console.


I tried transfering files using

with open(filename, "rb") as f:
    while True:
        bytes_read = f.read(BUFFER_SIZE)
        if not bytes_read:
            break
        s.sendall(bytes_read)

and

with open(filename, "wb") as f:
    while True:
        bytes_read = client_socket.recv(BUFFER_SIZE)
        if not bytes_read:    
            break
        f.write(bytes_read)

which would have been simpler, but it ended up fusing files together when downloading multiple at once, so I opted for what you can see above.

Also, even though the send('0'.encode()) and recv(1) significantly slow the transfer down, they are necessary to ensure that the client and the server work synchonously, and getting rid of them causes data loss. Increasing the buffer size can help speed up the process but setting it too high causes data loss as well.


Finally, as english isn’t my native language, I apology for any mistake I could have made. Feel free to correct me or ask for clarification.

Thanks for your time and have a nice day.

beginner – Todo App with JavaScript

I am learning JavaScript and this is a simple todo application I made which uses local storage. It is currently running at: https://koraytugay.github.io/vanillatodo/#. The code is as follows. I am open to any suggestions on how the structure / architecture or implementation details should/can be improved. Can be cloned from: https://github.com/koraytugay/vanillatodo and it looks like this:

enter image description here

index.html

<!DOCTYPE html>
<html>
<head>
  <title>VanillaTodo</title>
  <link rel="stylesheet" href="style.css"/>
</head>
<body>
<div id="container">
  <input id="new-todo-input" type="text">
  <h2>To Do Items</h2>
  <div id="todo-items"></div>
  <hr/>
  <a href="#" id="delete-all-todo-items">Delete All</a>
</div>
<script type="module" src="src/todoController.js"></script>
</body>
</html>

todoItemStorageService.js

export default (function() {
  const todoItems = 'todo-items';
  const idCounter = 'id-counter';

  function getTodoItems() {
    if (localStorage.getItem(todoItems) === null) {
      localStorage.setItem(todoItems, JSON.stringify(()));
      localStorage.setItem(idCounter, '1');
    }
    return JSON.parse(localStorage.getItem(todoItems));
  }

  function getNextTodoItemId() {
    const nextTodoItemId = parseInt(localStorage.getItem(idCounter));
    localStorage.setItem(idCounter, '' + (nextTodoItemId + 1));
    return nextTodoItemId;
  }

  function setTodoItems(items) {
    localStorage.setItem(todoItems, JSON.stringify(items));
  }

  function deleteTodoItem(id) {
    setTodoItems(getTodoItems().filter(todoItem => todoItem.id !== id));
  }

  function deleteTodoItems() {
    setTodoItems(());
  }

  function addTodoItem(todoItem) {
    setTodoItems((...getTodoItems(), todoItem));
  }

  function getTodoItem(id) {
    return getTodoItems().filter(todoItem => todoItem.id === id)(0);
  }

  function updateTodoItem(todoItem) {
    const allTodoItems = getTodoItems();
    const itemIndex = allTodoItems.findIndex(item => item.id === todoItem.id);
    allTodoItems(itemIndex).text = todoItem.text;
    allTodoItems(itemIndex).id = todoItem.id;
    allTodoItems(itemIndex).completed = todoItem.completed;
    setTodoItems(allTodoItems);
  }

  return {
    getNextTodoItemId,
    addTodoItem,
    getTodoItems,
    getTodoItem,
    updateTodoItem,
    deleteTodoItem,
    deleteTodoItems
  }
}());

todoService.js

import todoItemsStorageService from './todoItemsStorageService.js';

export default (function() {
  function Todo(text) {
    this.text = text;
    this.id = `todo-item-${todoItemsStorageService.getNextTodoItemId()}`;
    this.completed = false;
    todoItemsStorageService.addTodoItem(this);
  }

  function toggleTodoItemCompletedStatus(id) {
    const todoItem = todoItemsStorageService.getTodoItem(id);
    todoItem.completed = !todoItem.completed;
    todoItemsStorageService.updateTodoItem(todoItem);
  }

  const getTodoItems = () => todoItemsStorageService.getTodoItems();
  const deleteTodoItem = (id) => todoItemsStorageService.deleteTodoItem(id);
  const deleteTodoItems = () => todoItemsStorageService.deleteTodoItems();

  return {
    Todo,
    getTodoItems,
    toggleTodoItemCompletedStatus,
    deleteTodoItem,
    deleteTodoItems
  };
}());

todoController.js


(function() {
  const findById = id => document.querySelector(`#${id}`);
  const createElement = (tag, options) => document.createElement(tag, options);

  window.addEventListener('load', function() {
    refreshUi();
  });

  findById('new-todo-input').addEventListener('keydown', e => {
    if ('Enter' === e.key && e.target.value) {
      new todoService.Todo(e.target.value);
      e.target.value = '';
      refreshUi();
    }
  });

  findById('delete-all-todo-items').addEventListener('click', e => {
    todoService.deleteTodoItems();
    refreshUi();
  });

  function toggleTodoCompleteStatus(id) {
    todoService.toggleTodoItemCompletedStatus(id);
    refreshUi();
  }

  function deleteTodoItem(id) {
    todoService.deleteTodoItem(id);
    refreshUi();
  }

  function createTodoDiv(todoItem) {
    const todoDiv = createElement('div');
    todoDiv.id = todoItem.id;

    const markAsDoneCheckbox = createElement('input');
    markAsDoneCheckbox.setAttribute('type', 'checkbox');
    markAsDoneCheckbox.addEventListener('click', () => toggleTodoCompleteStatus(todoItem.id));

    const todoSpan = createElement('span');
    todoSpan.innerText = todoItem.text;

    const deleteTodoItemLink = createElement('a');
    deleteTodoItemLink.setAttribute('href', '#');
    deleteTodoItemLink.addEventListener('click', () => deleteTodoItem(todoItem.id));
    deleteTodoItemLink.innerText = '❌';

    if (todoItem.completed) {
      todoSpan.classList.add('done');
      markAsDoneCheckbox.setAttribute('checked', 'checked');
    }

    todoDiv.appendChild(markAsDoneCheckbox);
    todoDiv.appendChild(todoSpan);
    todoDiv.appendChild(deleteTodoItemLink);

    return todoDiv;
  }

  function refreshUi() {
    const todoItemsDiv = findById('todo-items');
    todoItemsDiv.innerHTML = '';
    todoService.getTodoItems().forEach(todoItem => todoItemsDiv.appendChild(createTodoDiv(todoItem)));
  }
})();

beginner – Print the row number that has the largest sum in a 2D array

Some guess

The code you provide is missing important information that we must guess.

Being a programmer means being able to present the problem and the solution without ambiguity. Here is one important and some pedantic ambiguities listed.

  • What type are the items referenced by array?

    We can assume they are int but depending on the compiler settings your code could still work for other types. The problem may be hidden behind warnings that we can not see.

    If for example the array contains unsigned int then adding what is a positive value (in the array) can be subtracted if the top bit is 1

  • What is row_count, is it a static typed value, a defined value (has no type), or …?

  • You provided no library references, eg #include <stdio.h> Yes it is a very standard include associated with printf but we are still left to guess this is a fact.

Rewrite

Taking your code at face value

Two bugs

  1. Sum will sum all rows as you do not reset its value for each row.

  2. The max value temp is initialized with the wrong value. It should have the lowest possible value. That means that largest_row may never get a value.

    Depending on the compiler setting what is printed could be a random value, or zero.

Poor design

The code is inefficient and the naming is poor.

  • largest_row is a function so give it a capital Largest_row

  • largest_row is not what the function does. It prints the index of the largest row. Using PrintIdxLargestRowSum would be better however it is too long. If we make the function return the largest row, the name could be IdxLargestSum

  • It is a little odd as you are checking for a max value as you are summing the row.

    First sum the row, then check for the max value.

  • Keep variables scoped as close as possible to the code they are used in. Declare sum inside the first loop.

Using your code as a template we get

// Assumes global row_count > 0
int Idx_largest_row(void) {
    int idx, max;
    for (int i = 0; i < row_count; i++) {
        int sum = 0
        for (int j = 0; j < row_count; j++) {
            sum += array(i)(j); 
        }
        if (i == 0 || (i > 0 && sum > max)) {
            max = sum;
            idx = i;
        }
    }
    return idx;
}

// use as
printf("%in", Idx_largest_row());

Example

The above rewrite is still rather poor in my view.

  • There should be two functions, one to sum a row the other to find the max sum.

  • The array and row counts should be an argument

  • The inner arrays should be of defined length

#include <stdio.h>

#define COL_COUNT  5
#define uint unsigned int

int rows()(COL_COUNT) = {
    {10,   2, 320, 344, -130},
    {30,  12, 330, 444, -160},
    {100,  2, 123, 207,   50},
    {102, 82, 530, 544, -150},
    {103, 72, 730, 444, -140}
};

int SumRow(int *row, uint count) {
    int sum = 0;
    for (uint i = 0; i < count; i++) { sum += row(i); }
    return sum;
}
uint LargestRowIdx(int rows()(COL_COUNT), uint rowCount) {
    uint idx = 0;
    int max = SumRow(rows(0), COL_COUNT);
    for (uint i = 1; i < rowCount; i++) {
        int sum = SumRow(rows(i), COL_COUNT);
        if (sum > max) { 
            max = sum; 
            idx = i;
        }
    }
    return idx;
}

void main() {
    printf("Index of largest sum: %un", LargestRowIdx(rows, 5));
    return;
}

Note that the number of rows is a magic number 5, however you should use a defined value or variable

Note I use unsigned int when indexing and rather than have to type all that I use the the defined #define uint unsigned int. There is no reason you can not use an int for indexes

Note I use camelCase names rather than snake_case. Which to use is up to you

beginner – Printing the ith row with the largest sum in a 2D array

void largest_row(void)
{
    int largest_row, temp = 0, sum = 0;

    for (int i = 0; i < row_count; i++)
    {
        for (int j = 0; j < row_count; j++)
        {
            sum += array(i)(j); //Array referenced here is globally defined
            if (sum > temp)
            {
                largest_row = i;
            }
            temp = sum;
        }
    }

    printf("%in", largest_row);

    return;
}

The function largest_row() prints the ith row of a 2d array that has the largest sum.

In what areas could my code or algorithm be improved (i.e. recursion implementation)? I think there is a better way, and I want to get exposed to well-designed codes and more efficient algorithms as I continue to learn to program.

As of now, I think I depend too much on loops and that limits my programming experience. Is it even right to think that way? For reference, and if you guys are familiar, I’m currently in week 3 of CS50x (infamous Tideman problem). I’m almost done with it but I want my code to be better. That’s the goal of my question at least if any of these is too vague already.

Criticize my Sudoku solver for improvements (C# beginner)

I recently started programming and chose C# as my first language. After a couple of weeks/month now I tried to make my own Sudoku solver in a console application. I’m happy with the result, and tried to clean up my code.

But I’m not sure what I can do better at this point. I was uncertain if I created too many functions? Some of them I actually only call once (like ValidateNumber(), ValidateSquare() & ValidateDimension()), simply because I thought the code look cleaner.

Any suggestions for improvements or if something is bad practice?

static void Main(string() args)
{
    int(,) puzzle = {{0,0,0,8,0,0,4,2,0},
                     {5,0,0,6,7,0,0,0,0},
                     {0,0,0,0,0,9,0,0,5},
                     {7,4,0,1,0,0,0,4,0},
                     {0,0,9,0,3,0,7,0,0},
                     {0,0,0,0,0,7,0,4,8},
                     {8,0,0,4,0,0,0,0,0},
                     {0,0,0,0,9,8,0,0,3},
                     {0,9,5,0,0,3,0,0,0}};

    PrintSudoku(puzzle);

    Console.WriteLine("Press 'enter' to solve.");
    Console.ReadLine();
    Console.WriteLine("Solving... This may take a second. n");
    
    SolveSudoku(puzzle);
        
}

private static void SolveSudoku(int(,) puzzle)
{
    //Copy input sudoku to a new solution array
    int(,) solution = new int(9, 9);
    Array.Copy(puzzle, 0, solution, 0, puzzle.Length);

    //Loop through each cell in the sudoku
    for (int column = 0; column < 9; column++)
    {
        for (int row = 0; row < 9;)
        {
            if (puzzle(column, row) == 0) //If original cell != 0, It's already a difined number and should not be changed.
            {
                for (int i = 0; i < 10; i++)
                {
                    //Increment cell with 1
                    solution(column, row)++;

                    //If cell = 10, all tested numbers failed, reset to 0 and go back to previous cell which originally had a 0 value
                    if (solution(column, row) == 10)
                    {
                        solution(column, row) = 0;

                        do
                        {
                            if (row == 0)
                            {
                                row += 8;
                                column -= 1;
                            }
                            else
                            {
                                row -= 1;
                            }
                        } while (puzzle(column, row) != 0);

                        break;
                    }
                    //Else if number does not collide with any other row/column/square, continue with next cell
                    else if (ValidateNumber(solution, column, row))
                    {
                        row++;
                        break;
                    }
                    else //If cell != 10 and number validation failed, continue with the next number.
                    {
                        continue;
                    }
                }
            }
            // original cell != 0, continue with next cell.
            else
            {
                row++;
            }

        }

    }

    PrintSudoku(solution);
    Console.ReadLine();

}

private static bool ValidateNumber(int(,) arr, int row, int column)
{
    //Validate that both 3x3 square and dimension(row/column) have no other cell with the same value as current array number
    if (ValidateSquare(arr, row, column) && ValidateDimension(arr, row, column))
    {
        return true;
    }
    return false;

}

private static bool ValidateDimension(int(,) arr, int row, int column)
{
    //Check if the current cell match any other cell in the same row, if so return false
    for (int a = 0; a < 9; a++)
    {
        if (column == a) //don't compare the cell with itself
        {
            continue;
        }
        if (arr(row, column) == arr(row, a))
        {
            return false;
        }
    }

    //Check if the current cell match any other cell in the same column, if so return false
    for (int b = 0; b < 9; b++)
    {
        if (row == b)
        {
            continue;
        }
        if (arr(row, column) == arr(b, column)) //don't compare the cell with itself
        {
            return false;
        }
    }

    //if no other cell with same value, return true
    return true;

}

private static bool ValidateSquare(int(,) arr, int row, int column)
{
    //Compare that the current cells 3x3 grid doesn't contain the same number as current cell. 
    int rowSquare = CurrentSquare(row);
    int columnSquare = CurrentSquare(column);

    for (int i = rowSquare; i < rowSquare + 3; i++)
    {
        for (int j = columnSquare; j < columnSquare + 3; j++)
        {
            if (arr(i, j) == arr(row, column))
            {
                if (i == row && j == column) //don't compare the cell with itself
                {
                    continue;
                }
                return false;
            }
        }
    }

    return true;
}

private static int CurrentSquare(int coordinate)
{
    //Give the coordinate of input dimension (row/column/depth), and defines which 3x3 square of the puzzle it belongs to in the 9x9 grid. 
    int square = 0;
    switch (coordinate)
    {
        case 0:
        case 1:
        case 2:
            square = 0; //Square1 in grid, Square1 start at index 0
            break;

        case 3:
        case 4:
        case 5:
            square = 3; //Square2 in grid, Square2 start at index 3
            break;

        case 6:
        case 7:
        case 8:
            square = 6; //Square3 in grid, Square3 start at index 6
            break;
    }
    return square;
}

private static void PrintSudoku(int(,) sudoku)
{
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            if (j % 3 == 0 && j != 0)
            {
                Console.Write("| ");
            }
            Console.Write(sudoku(i, j) + " ");
        }

        if (i % 3 == 2 && i != 8)
        {
            Console.WriteLine();
            Console.Write("------+-------+------");                
        }
        Console.WriteLine();
    }
    Console.WriteLine();
}

beginner – How to speed up the VBA scraping process

I want to scrape 25000 addresses using Column A cell values as search strings. I’m using the following code, it is working fine but it’s too slow to extract 25000 results. Is there any way to speed up the process, like opening multiple addresses at once or something else? I’m pretty new to VBA coding. Any help would be appreciated.

Sub pullAddresses()

    Dim IE As Object
    Dim Doc As HTMLDocument
    
    Set IE = CreateObject("InternetExplorer.Application")
    IE.Visible = True
    
    
    
    For introw = 2 To 10
        searchstring = ThisWorkbook.Sheets("Sheet1").Range("A" & introw).Value
        IE.navigate ("https://www.google.com/search?q=" & searchstring)
        
        Do Until IE.readyState = READYSTATE_COMPLETE
        DoEvents
        Loop
        
        
        Set ht = IE.document
        
        ''Application.Wait (Now() + TimeValue("00:00:02"))
        
        a = ht.getElementsByClassName("desktop-title-content")(0).innerText
        b = ht.getElementsByClassName("desktop-title-subcontent")(0).innerText
        
        ThisWorkbook.Sheets("Sheet1").Range("B" & introw).Value = a & ", " & b
    
    Next

End Sub

beginner – Prerelease IGCSE Computer Science Train Q, Im not sure why im getting this synntax error

I am getinng a syntax error on the while part, im not too sure why though, the question is IGCSE Cambridge International Computer Science 0478/22. I am new to coding and am not sure why this is happening.

costTicket = 25.00

uptrainTimes = (9,11,13,15)
uptrainMoney = (0.0,0.0,0.0,0.0)
uptrainTickets = (480,480,480,480)

downtrainTimes = (10,12,14,16)
downtrainMoney = (0.0,0.0,0.0,0.0)
downtrainTickets = (480,480,480,480)

print("Train times and available tickets are displayed in this table: n")
print("Train times t Available tickets t Total Money n")
for x in range (0,4):
    print (uptrainTimes(x), "tt", uptrainTickets(x), "ttt" , uptrainMoney(x))
    print (downtrainTimes(x), "tt", downtrainTickets(x), "ttt" , downtrainMoney(x))

sellingTicket = "yes"

timeChoice = int(input("What time would you like to go up : 9, 11,13 or 15?") 
while timeChoice not in (9,11,13 or 15):
    print ("That is not a valid time")
    timeChoice = int(input("What time would you like to go up : 9, 11,13 or 15?")

indexUp = uptrainTimes.index(timeChoice)

beginner – Java dependency injection and hiding details of methods in “Database”-class

I recently posted a bunch of code of my to-do list application and after getting some very helpful and good suggestions on how to improve, I took a shot at it! Here’s a link to the former post I made -> A to-do list application written with Java

I have now used the one and the same instance of storage in each of the classes that need it, instead of creating new instances for each class. Namely, the Login-class and the UI-class.
I’ve also created two interfaces and defined methods to deal with the Storage-class. Also I adjusted some of the Storage-classes methods and added new ones, in order to hide the details of the storage-operations from the Login and UI-classes.

I think I nailed it with the dependency injection by passing that one instance of Storage on the constructors of Login and UI-classes.
In the StorageInstance-class, I have a method which returns that instance of a storage. Is this the correct way to go about the dependency injection? Namely, that I use the method returnStorage() to do storage-related actions?

As for the interfaces, I wanted to hide the details of what happens in the Storage-class so the UI and Login wouldn’t have any idea what is going on under the surface, except that something is happening that relates to the storage-class.
Is this the correct way to go about it? Any and all improvements and help are welcome!

I will not post the whole application code in here, only the classes I’ve changed. The whole project can be viewed from the link above.

public class Storage {

    private HashMap<String, ToDoList> toDoLists;
    private HashMap<String, User> map;
    private File UsernamesAndPasswords;
    private File UsersToDoLists;
    private User user;

    Storage() {
        this.UsernamesAndPasswords = new File("UsernamesAndPasswords.ser");
        this.UsersToDoLists = new File("ToDoLists.ser");
        loadUserNamesAndPasswords(UsernamesAndPasswords);
        loadUsersToDoLists(UsersToDoLists);
    }

    public void saveUsersToDoLists() {
        try {
            FileOutputStream fosTwo = new FileOutputStream(UsersToDoLists);
            ObjectOutputStream oosTwo = new ObjectOutputStream(fosTwo);

            oosTwo.writeObject(this.toDoLists);
            oosTwo.flush();
            oosTwo.close();
            fosTwo.close();
        } catch (IOException e) {
            System.out.println("Exception happened. saveUsersList");
        }
    }

    public void loadUsersToDoLists(File file) {
        if (file.length() == 0) {
            toDoLists = new HashMap<>();
            this.saveUsersToDoLists();
        }
        try {
            FileInputStream fisTwo = new FileInputStream(UsersToDoLists);
            ObjectInputStream oisTwo = new ObjectInputStream(fisTwo);

            toDoLists = (HashMap<String, ToDoList>) oisTwo.readObject();
            oisTwo.close();
            fisTwo.close();
        } catch (Exception e) {
            System.out.println("Exception happened. loadUsersList");
        }
    }

    public void saveUserNamesAndPasswords(HashMap<String, User> loginInfo) {
        try {
            FileOutputStream fos = new FileOutputStream(UsernamesAndPasswords);
            ObjectOutputStream oos = new ObjectOutputStream(fos);

            oos.writeObject(this.map);
            oos.flush();
            oos.close();
            fos.close();
        } catch (IOException e) {
            System.out.println("Exception happened. saveUsernames");
        }
    }

    public void loadUserNamesAndPasswords(File file) {
        //If the file is empty then this method creates a new empty hashmap and saves it
        //in the file
        if (file.length() == 0) {
            map = new HashMap<>();
            this.saveUserNamesAndPasswords(map);
        }
        try {
            FileInputStream fis = new FileInputStream(UsernamesAndPasswords);
            ObjectInputStream ois = new ObjectInputStream(fis);

            map = (HashMap<String, User>) ois.readObject();
            ois.close();
            fis.close();
        } catch (Exception e) {
            System.out.println("Exception happened. loadUserNames");
        }
    }

    public HashMap<String, User> getUserNamesAndPasswords() {
        return this.map;
    }

    public File getUsernamesAndPasswordsFile() {
        return this.UsernamesAndPasswords;
    }

    public HashMap<String, ToDoList> getToDoLists() {
        return this.toDoLists;
    }

    public File getUsersToDoListsFile() {
        return this.UsersToDoLists;
    }

    public void createUser(String userName, String firstName, String lastName, String password) {
        this.user = new User(firstName, lastName, password);
        this.getUserNamesAndPasswords().putIfAbsent(userName, user);
        this.saveUserNamesAndPasswords(this.getUserNamesAndPasswords());
        this.getToDoLists().putIfAbsent(userName, this.user.getUsersToDoList());
        this.saveUsersToDoLists();
    }

    public void validateUsername(String username, String password) {
        if (this.getUserNamesAndPasswords().get(username).passwordEquals(password)) {
            this.user = getUserNamesAndPasswords().get(username);
            this.user.setList(this.getToDoLists().get(username));
        }
    }

    public User returnUser() {
        return this.user;
    }
}

public class UI implements InterfaceUI {

    private final Scanner reader;
    private final Storage storage;
    private Login login;
    private User user;

    public UI(StorageInstance si) {
        this.reader = new Scanner(System.in);
        this.storage = si.getStorage();
        this.login = new Login(si);
    }

    public void start() {
        System.out.println("Login or register");
        String fromUser = reader.nextLine().trim();
        if (fromUser.equalsIgnoreCase("register")) {
            System.out.print("Your username:");
            String userName = reader.nextLine();
            System.out.print("Your first name:");
            String firstName = reader.nextLine();
            System.out.print("Your last name:");
            String lastName = reader.nextLine();
            System.out.print("Your password:");
            String password = reader.nextLine();
            createUser(userName, firstName, lastName, password);
        }
        login.logIn();
        this.user = login.returnUser();
        this.user.getUsersToDoList().printToDoList();

        while (true) {
            System.out.println("");
            System.out.println("1: Add a to-do item.");
            System.out.println("2. Remove a to-do item.");
            System.out.println("3. Print a list of my to-do items.");
            System.out.println("4. Quit and save");
            System.out.print("Type the number of desired action: ");

            String input = reader.nextLine();

            if (input.equals("4")) {
                saveUsersList();
                System.out.println("Quitting!");
                break;
            } else if (input.equals("1")) {
                System.out.println("What would you like to add?");
                String add = reader.nextLine();
                toDo item = new toDo(add);
                this.user.getUsersToDoList().addToDo(item);
            } else if (input.equals("2")) {
                if (this.user.getUsersToDoList().getList().isEmpty()) {
                    System.out.println("List is empty.");
                    continue;
                }
                System.out.println("");
                this.user.getUsersToDoList().printToDoList();
                System.out.print("Type the index of the item you wish to remove: ");
                int remove = Integer.parseInt(reader.nextLine());
                this.user.getUsersToDoList().removeToDo(remove);
            } else if (input.equals("3")) {
                System.out.println("");
                this.user.getUsersToDoList().printToDoList();
            }
        }
    }

    public void createUser(String userName, String firstName, String lastName, String password) {
        storage.createUser(userName, firstName, lastName, password);
    }

    public void saveUsersList() {
        storage.getToDoLists().put(login.returnUsername(), this.user.getUsersToDoList());
        storage.saveUsersToDoLists();
    }
}

public class Login implements LoginInterface {

    private User user;
    private final Storage storage;
    private Scanner reader;
    private String username;

    public Login(StorageInstance si) {
        this.storage = si.getStorage();
        this.reader = new Scanner(System.in);
    }

    public void logIn() {
        System.out.println("Username:");
        this.username = reader.nextLine();
        System.out.println("Password:");
        String password = reader.nextLine();
        try {
            validateUser(this.username, password);
                System.out.println("Welcome " + user.getFirstName() + "!");
        } catch (NullPointerException npe) {
            System.out.println("Incorrect username or password. Please try again!");
            this.logIn();
        }
    }

    public User returnUser() {
        return this.user;
    }

    public String returnUsername() {
        return this.username;
    }

    public void validateUser(String username, String password) {
        storage.validateUsername(username, password);
        this.user = storage.returnUser();
    }
}

public class StorageInstance {
    private Storage storage;


    public StorageInstance() {
        this.storage = new Storage();
    }

    public Storage getStorage() {
        return this.storage;
    }
}

public interface InterfaceUI {

    public void createUser(String userName, String firstName, String lastName, String password);

    public void saveUsersList();
}

public interface LoginInterface {

    public void validateUser(String username, String password);
}