Repository: TheAlgorithms/Python

Issue:
Delete base85 algorithm
### Describe your change:
Re #6216

Normally, I'm not in favour of just deleting algorithms, but I would make the argument that this is not an algorithm, rather just a snippet of code that utilises another library.

Per `CONTRIBTUING.md`
> Algorithms in this repo should not be how-to examples for existing Python packages. Instead, they should perform internal calculations or manipulations to convert input values into different output values
This `base85` algorithm has essentially got two lines of code that purely utilise a singular library. The doctests only test an external library

This repository should not contains examples on how to use a certain library, that would be the library documentation here
https://docs.python.org/3/library/base64.html


* [ ] Add an algorithm?
* [ ] Fix a bug or typo in an existing algorithm?
* [ ] Documentation change?
* [x] Delete an algorithm

### Checklist:
* [x] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md).
* [x] This pull request is all my own work -- I have not plagiarized.
* [x] I know that pull requests will not be merged if they fail the automated tests.
* [x] This PR only changes one algorithm file.  To ease review, please open separate PRs for separate algorithms.
* [x] All new Python files are placed inside an existing directory.
* [x] All filenames are in all lowercase characters with no spaces or dashes.
* [x] All functions and variable names follow Python naming conventions.
* [x] All function parameters and return values are annotated with Python [type hints](https://docs.python.org/3/library/typing.html).
* [x] All functions have [doctests](https://docs.python.org/3/library/doctest.html) that pass the automated testing.
* [x] All new algorithms include at least one URL that points to Wikipedia or another similar explanation.
* [x] If this pull request resolves one or more open issues then the description above includes the issue number(s) with a [closing keyword](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue): "Fixes #ISSUE-NUMBER".



Discussion:
@tianyizheng02 Opinion?

Will also create a pr to delete 
https://github.com/TheAlgorithms/Python/blob/master/ciphers/base32.py

However, I like the [base16](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base16.py) and the [base64](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base64.py) because they actually use calculations, not a library

Also very open to further implementations of `base32` and `base85`, just an actual algorithm that does not solely use a library
Obviously I agree that we can't have this "algorithm" simply utilize a library, but personally I'd rather we keep the file around and encourage other contributors to reimplement the algorithm instead. Unless one of us reimplements the algorithm right after this file is deleted, there's no guarantee that someone else will contribute the same algorithm again. Having the file around could at least serve as a reminder of an ongoing issue.

Resolving patch:
diff --git a/ciphers/base85.py b/ciphers/base85.py
--- a/ciphers/base85.py
+++ b/ciphers/base85.py
@@ -1,30 +1,55 @@
-import base64
+"""
+Base85 (Ascii85) encoding and decoding
 
+https://en.wikipedia.org/wiki/Ascii85
+"""
 
-def base85_encode(string: str) -> bytes:
+
+def _base10_to_85(d: int) -> str:
+    return "".join(chr(d % 85 + 33)) + _base10_to_85(d // 85) if d > 0 else ""
+
+
+def _base85_to_10(digits: list) -> int:
+    return sum(char * 85**i for i, char in enumerate(reversed(digits)))
+
+
+def ascii85_encode(data: bytes) -> bytes:
     """
-    >>> base85_encode("")
+    >>> ascii85_encode(b"")
     b''
-    >>> base85_encode("12345")
+    >>> ascii85_encode(b"12345")
     b'0etOA2#'
-    >>> base85_encode("base 85")
+    >>> ascii85_encode(b"base 85")
     b'@UX=h+?24'
     """
-    # encoded the input to a bytes-like object and then a85encode that
-    return base64.a85encode(string.encode("utf-8"))
+    binary_data = "".join(bin(ord(d))[2:].zfill(8) for d in data.decode("utf-8"))
+    null_values = (32 * ((len(binary_data) // 32) + 1) - len(binary_data)) // 8
+    binary_data = binary_data.ljust(32 * ((len(binary_data) // 32) + 1), "0")
+    b85_chunks = [int(_s, 2) for _s in map("".join, zip(*[iter(binary_data)] * 32))]
+    result = "".join(_base10_to_85(chunk)[::-1] for chunk in b85_chunks)
+    return bytes(result[:-null_values] if null_values % 4 != 0 else result, "utf-8")
 
 
-def base85_decode(a85encoded: bytes) -> str:
+def ascii85_decode(data: bytes) -> bytes:
     """
-    >>> base85_decode(b"")
-    ''
-    >>> base85_decode(b"0etOA2#")
-    '12345'
-    >>> base85_decode(b"@UX=h+?24")
-    'base 85'
+    >>> ascii85_decode(b"")
+    b''
+    >>> ascii85_decode(b"0etOA2#")
+    b'12345'
+    >>> ascii85_decode(b"@UX=h+?24")
+    b'base 85'
     """
-    # a85decode the input into bytes and decode that into a human readable string
-    return base64.a85decode(a85encoded).decode("utf-8")
+    null_values = 5 * ((len(data) // 5) + 1) - len(data)
+    binary_data = data.decode("utf-8") + "u" * null_values
+    b85_chunks = map("".join, zip(*[iter(binary_data)] * 5))
+    b85_segments = [[ord(_s) - 33 for _s in chunk] for chunk in b85_chunks]
+    results = [bin(_base85_to_10(chunk))[2::].zfill(32) for chunk in b85_segments]
+    char_chunks = [
+        [chr(int(_s, 2)) for _s in map("".join, zip(*[iter(r)] * 8))] for r in results
+    ]
+    result = "".join("".join(char) for char in char_chunks)
+    offset = int(null_values % 5 == 0)
+    return bytes(result[: offset - null_values], "utf-8")
 
 
 if __name__ == "__main__":


Test patch: