Collatz conjecture is a simple algorithm. That ultimately results in an infinite loop between 1 and 4.
Depending on the user input there will be an amount of loops prior to the 1 to 4 trap.
All we want to do here is, to calculate the number of loops prior to the trap based on a senders initial value. Then return this value to the sender. (( I'm just beginning here, hope this is correct thread ))
pragma solidity >=0.7.0 <0.9.0;
contract collatzConjecture {
// Below completely guessing I am mapping integers to an address
mapping(address => uint256) public userInput;
mapping(address => uint256) public userOutput;
function doOdds(uint256 _oddNumber) private pure returns(uint256){
//collatzConjecture, if the value is odd then * 3 + 1
uint256 oddNumber;
oddNumber = _oddNumber * 3 + 1;
return oddNumber;
}
function doEvens(uint256 _evenNumber) private pure returns(uint256){
//collatzConjecture, if the value is even then / 2
uint256 evenNumber;
evenNumber = _evenNumber / 2;
return evenNumber;
}
function isOdd(uint256 _number) private pure returns(uint256){
//just checking if the value is odd or even
uint256 checkingNumber = _number - _number;
if (checkingNumber != 0){
return 0;
}else{
return 1;
}
}
function loopCalculations(uint256 _userInput) private pure returns(uint256){
// This is the collatzConjecture looping the _userInput
uint256 userValue = _userInput;
uint256 loopCount = 0;
do {
loopCount ++; // Want to return this to the sender when finsihed
if (isOdd(userValue) != 0){
userValue = doOdds(userValue);
}else{
userValue = doEvens(userValue);
}
} while (userValue != 1);
return loopCount;
}
// Below I'm guessing this is pretty wrong.
// I am trying to immediately trying to return the result to the sender
// using the same function the sender would use to input an amount ?
function iniContract(uint256 _userInput) public{
userInput[msg.sender] = loopCalculations(_userInput);
}
}
The error from the vm was the transaction has been reverted to its initial state.
Your may want to take a second look at the isOdd and f_isOdd functions. In isOdd, uint256 checkingNumber = _number - _number;, checkingNumber is always 0, isn't it? In f_isOdd, the name isOdd seems to be returning a boolean value yet the actual returned value is an uint256.
There is nothing more motivating than the drive to recover from the initial public idiocy, like isOdd for example, and you are correct it was meaningless because anything take away anything is nothing.
f_isOdd, on the other hand is working and it is returning a 1 or a 0, but I have not looked at the bool variable, well I tried it but did it wrong. Thanks I will correct this.
Regarding the integers, I will have to read some being unsure of how big these whole numbers can be, I also have seen no doubles anywhere. Hence more reading to do there. Thanks
I just attempted to take the Eth out of the account, can not. I can't see user balance. So for now I just put an initial balance in the constructor so I could get it going. Its all counting up now, but I have much to learn.
This is so far.
pragma solidity ^0.8.4;
contract c_collatzConjecture {
uint256 private iniValue;
uint256 private maxLoops;
address public user = msg.sender;
mapping (address => uint) public balances;
constructor() {
maxLoops = 100000000;
}
event returnedValue(address from, address to, uint amount);
error joinTheClub(uint requested, uint available);
function f_doOdds(uint256 _odds) private pure returns (uint256) {return _odds * 3 + 1;}
function f_doEvens(uint256 _evens) private pure returns (uint256) {return _evens / 2;}
function f_isOdd(uint256 _number) private pure returns(uint256){return _number % 2;}
function f_collatzConjecture(uint256 _iniValue) private view returns (uint256) {
uint256 loopCount = 0;
do {
loopCount += 1;
if (f_isOdd(_iniValue) == 1){
_iniValue = f_doOdds(_iniValue);
}else{
_iniValue = f_doEvens(_iniValue);
}
} while (_iniValue != 1 && loopCount < maxLoops);
return loopCount;
}
function f_doTransferStuff(uint256 _iniValue) public {
balances[user] = balances[user] + _iniValue;
if (_iniValue > balances[user]) revert joinTheClub({
requested: _iniValue,
available: balances[user]
});
balances[user] -= _iniValue;
balances[user] += f_collatzConjecture(_iniValue);
emit returnedValue (user, user, f_collatzConjecture(_iniValue));
}
}
I like revert that is a pretty nice touch to an if statement.
The error I am receiving is stating that the function should be payable, however an internal function cannot be payable hence I am confused how to tag this internal function f_collatzConjecture.
//seen in full above above
function f_collatzConjecture(uint256 _iniValue) internal virtual returns (uint256)
Could anyone please explain this to me. ?
Much appreciated.
I removed the constructor. The maximum loops must be set now.
When I tried to encode the constructor with the value used to deploy it was not accepted.
There is no owner on this contract anyone can enter a value. What it does is quite simple.
You enter a value and it returns the amount of loops it takes for the conjecture to reach 1.
The initial value is stored as the first mapped key, and each key following stores the values for each loop achieved throughout the conjecture.
It would b good to see the results plotted for results across loops.